public with sharing class CommonUtils {

    //查询  医院下的科室 包括战略和普通科室
    // content 查询内容
    // ParentId 父ID
    public static string GetYYChilders(String content,String ParentId)
    {
        String sql = 'select ';
        String props = GetSqlToPorps(account.SObjectType);
        sql += props;
        sql += ' from account';
        if(ParentId != null && ParentId != '')
        {
            sql += ' where (Parentid = :ParentId or Parent.Parentid = :ParentId)';
        }
        if(content != null && content != '')
        {
            content = '%'+content+'%';
            sql += ' and Name like :content ';
        }
       
        sql += ' limit 5 ';
        List<account> arrays = Database.query(sql);
        return JSON.serialize(arrays);  
    }

  


     //查询  普通科室
     public static string GetPTKS(String content, List<String> ParentIds, Boolean checkOwner)
     {
        String paramYy = 'HP';
        String sql = 'select ';
        String props = GetSqlToPorps(account.SObjectType);
        sql += props;
        sql += ' from account';
        sql += ' where Parent.Parent.RecordType_DeveloperName__c   = :paramYy';
        if(content != null && content != '')
        {
            content = '%'+content+'%';
            sql += ' and Name like :content ';
        }
        if(ParentIds != null && ParentIds.size() > 0)
        {
            sql += ' and Parent.Parentid in :ParentIds ';
        }
        if (checkOwner) {
            String userId = UserInfo.getUserId();
            sql += ' and OwnerId = :userId';
        }
        sql += ' limit 5 ';
        List<account> arrays = Database.query(sql);
        return JSON.serialize(arrays);  
     }
 

     //查询  普通科室
    //  public static string GetPTKSByYYParent(String content,String ParentId)
    //  {
    //      List<String> listTemp = new List<String>();
    //      listTemp.add('Department_Class_OTH');
    //      listTemp.add('Department_Class_BF');
    //      listTemp.add('Department_Class_GYN');
    //      listTemp.add('Department_Class_GS');
    //      listTemp.add('Department_Class_URO');
    //      listTemp.add('Department_Class_GI');
    //      listTemp.add('Department_Class_ENT');
    //      listTemp.add('Department_Class_ET');
    //      String sql = 'select ';
    //      String props = GetSqlToPorps(account.SObjectType);
    //      sql += props;
    //      sql += ' from account';
    //      sql += ' where Parent.RecordType_DeveloperName__c   in :listTemp';
    //      if(content != null && content != '')
    //      {
    //          content = '%'+content+'%';
    //          sql += ' and Name like :content ';
    //      }
    //      if(ParentId != null && ParentId != '')
    //      {
    //          sql += ' and Parent.Parentid = :ParentId ';
    //      }
    //      sql += ' limit 5 ';
    //      List<account> arrays = Database.query(sql);
    //      return JSON.serialize(arrays);  
    //  }
     


    //查询 战略科室
       // content 查询内容
    // ParentId 父ID
    public static string GetZLKS(String content,String[] ParentId)
    {
        
        String paramYy = 'HP';
        String sql = 'select ';
        String props = GetSqlToPorps(account.SObjectType);
        sql += props;
        sql += ' from account';
        sql += ' where Parent.RecordType_DeveloperName__c  = :paramYy';
        if(content != null && content != '')
        {
            content = '%'+content+'%';
            sql += ' and Name like :content ';
        }
        if(ParentId != null && ParentId.size() > 0)
         {
             sql += ' and Parentid in :ParentId ';
         }
        sql += ' limit 8 ';
        List<account> arrays = Database.query(sql);
        return JSON.serialize(arrays);  
    }


    //查询 医院
       // content 查询内容
    public static string GetYY(String content)
    {
        List<String> listTemp = new List<String>();
        listTemp.add('HP');
        String sql = 'select ';
        String props = GetSqlToPorps(account.SObjectType);
        sql += props;
        sql += ' from account';
        sql += ' where RecordType_DeveloperName__c  in :listTemp and Is_Active__c = \'有効\' ';
        if(content != null && content != '')
        {
            content = '%'+content+'%';
            sql += ' and Name like :content ';
        }
        sql += ' limit 5 ';
        List<account> arrays = Database.query(sql);
        return JSON.serialize(arrays);  
    }


    // ParentId 父ID
    public static String GetAccountPrentID(String Id)
    {
        string sql = 'SELECT  Id from account where parentId = :Id limit 100 ';
        List<account> arrays = Database.query(sql);
        return JSON.serialize(arrays);  
    }
    //获取父节点
    // ID 客户的ID
    public static string GetParent(String Id)
    {
        Schema.SObjectType type = account.SObjectType;
        QueryWrapper query = new QueryWrapper(type);
        query.eq('Id', Id);
        List<account> arrays = DataBasePlus.listPlus(query);
        ParentAccount account  = new ParentAccount();
        // return JSON.serialize(arrays);  
        if(arrays[0].ParentId == null || arrays[0].RecordType_DeveloperName__c == 'HP') 
        {
            return JSON.serialize(account); 
        }

        QueryWrapper querytemp = new QueryWrapper(type);
        querytemp.eq('Id',arrays[0].Parentid);
        List<account> arraysTemp = DataBasePlus.listPlus(querytemp);
        if(arraysTemp[0].ParentId == null || arraysTemp[0].RecordType_DeveloperName__c == 'HP' )
        {
            
            account.yy = arraysTemp[0];
            return JSON.serialize(account);  
        }else
        {
            QueryWrapper queryTest = new QueryWrapper(type);
            queryTest.eq('Id',arraysTemp[0].Parentid);
            List<account> arraysTest = DataBasePlus.listPlus(queryTest);
            account.zlxs = arraysTemp[0];
            account.yy = arraysTest[0];
            return JSON.serialize(account);  
        }
    }
    //定义动态获取选项值的构造类
    public class ParentAccount {
        public account zlxs;
        public account yy;
    }
    
   // 查询改对象的所有有权限的属性
    // type 对象类型
    public static string GetSqlToPorps(Schema.SObjectType type)
    {
        Schema.DescribeSObjectResult results = type.getDescribe();
        String sql = '';
        //获取表中所有列的字段
        Map<String, Schema.SObjectField> fieldMap = results.fields.getMap();
        //字段拼接成字符串
        for(String keyset : fieldMap.keySet()) {
            Schema.DescribeFieldResult checksObjectField=fieldMap.get(keyset).getDescribe();
            if(checksObjectField.isAccessible()==true){
                if(checksObjectField.isAccessible()){
                    if(sql == ''){
                        sql = keyset;
                    }else{
                        sql = sql + ',' + keyset;
                    }
                }
            }
        }
        return sql;
    }
    //查询对象上所有的 列表类型的对象的 所有值
    // taskStatusfieldResult 对象上的列表的字段类型
    public static string GetSelectedValues( Schema.DescribeFieldResult taskStatusfieldResult ) {
         map<string, list<pickerWrapper>> pickerFields = new map<string, list<pickerWrapper>>();
         list<pickerWrapper> taskStatusOptions = new list<pickerWrapper>();
         // Schema.DescribeFieldResult taskStatusfieldResult = Product_Score_Table_History__c.Id.getDescribe();
         List<Schema.PicklistEntry> taskStatusple = taskStatusfieldResult.getPicklistValues();
         for ( Schema.PicklistEntry pickListVal : taskStatusple) {
             pickerWrapper temppickerWrapper =
                 new pickerWrapper(pickListVal.getLabel(), pickListVal.getValue());
             taskStatusOptions.add(temppickerWrapper);
         }
         pickerFields.put('taskStatusOptions', taskStatusOptions);
   
         List<pickerWrapper> pickerWrapperList = pickerFields.get('taskStatusOptions');
   
         String TempStr = Json.serialize(pickerWrapperList);
         return TempStr;
     }
   
   
     //定义动态获取选项值的构造类
     public class pickerWrapper {
         @AuraEnabled
         public string label;
         @AuraEnabled
         public string value;
         public pickerWrapper(string label, string value) {
             this.label = label;
             this.value = value;
         }
   
     }
    

     // ==========PICK List =============
     //查询 对象的依赖字段
     // objApiName  查询的对象名
     // controlField 控制字段名
     // dependentField 依赖字段名
     @AuraEnabled(cacheable = true)
    public static List<PicklistValue> getPicklistValues(String objApiName, String controlField, String dependentField){
        List<PicklistValue> pickListValues = new List<PicklistValue>();
        // if(String.isBlank(objApiName) || String.isBlank(controlField) || String.isBlank(dependentField)) {
        //     return null;
        // }
        
        //Identify the sobject type from the object name using global schema describe function
        Schema.SObjectType targetType = Schema.getGlobalDescribe().get(objApiName);
        //Create an empty object based up on the above the sobject type to get all the field names
        Schema.sObjectType objType = targetType.newSObject().getSobjectType();
        //fetch the all fields defined in the sobject
        Map<String, Schema.SObjectField> objFieldMap = objType.getDescribe().fields.getMap();
        //Get the controlling and dependent picklist values from the objFieldMap
        List<Schema.PicklistEntry> controlledPLEntries = objFieldMap.get(controlField).getDescribe().getPicklistValues();
        List<Schema.PicklistEntry> dependentPLEntries = objFieldMap.get(dependentField).getDescribe().getPicklistValues();

        // Wrap the picklist values using custom wrapper class – PicklistValue
        for (Schema.PicklistEntry entry : controlledPLEntries) {
            PicklistValue picklistValue = new PicklistValue(entry.isActive(), entry.isDefaultValue(), entry.getLabel(), entry.getValue());
            pickListValues.add(picklistValue);
        }
        //ValidFor is an indicator value for the controlling field which is base64 encrypted
        //base64 value should be convered to 6bit grouped binary and 1 indicate the controlling field in a certain order
        //Also,validFor value only be shown when it is serialized so it should be serialized then deserialized using PicklistValue wrapper class
        for(PicklistValue plVal : deserializePLEntries(dependentPLEntries)) {
            String decodedInBits = base64ToBits(plVal.validFor);
            
            for(Integer i = 0; i< decodedInBits.length(); i++) {
                // For each bit, in order: if it's a 1, add this label to the dependent list for the corresponding controlling value
				String bit = decodedInBits.mid(i, 1);
                if (bit == '1') {
                    PicklistValue dependentPLValue = new PicklistValue(plVal.active, plVal.defaultValue, plVal.label, plVal.value);
                    //Dependent picklist value is mapped to its parent controlling value through 'dependents' attribute in the PicklistValue wrapper class
                    if(pickListValues.get(i).dependents == null ) {
                        pickListValues.get(i).dependents = new List<PicklistValue>{dependentPLValue};
                    }else{
                        pickListValues.get(i).dependents.add(dependentPLValue);
                    }
                }
            }
        }
        return pickListValues;
    }

    private static List<PicklistValue> deserializePLEntries(List<Schema.PicklistEntry> plEntries) {
		return (List<PicklistValue>)
			JSON.deserialize(JSON.serialize(plEntries), List<PicklistValue>.class);
    }
    //Available base64 charecters
    private static final String BASE_64_CHARS = '' +'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +'abcdefghijklmnopqrstuvwxyz' +'0123456789+/';
    
    // Convert decimal to binary representation (alas, Apex has no native method 🙁
	//    eg. 4 => '100', 19 => '10011', etc.
	// Method: Divide by 2 repeatedly until 0. At each step note the remainder (0 or 1).
	// These, in reverse order, are the binary.
	private static String decimalToBinary(Integer val) {
		String bits = '';
		while (val > 0) {
			Integer remainder = Math.mod(val, 2);
			val = Integer.valueOf(Math.floor(val / 2));
			bits = String.valueOf(remainder) + bits;
		}
		return bits;
	}

	// Convert a base64 token into a binary/bits representation
	// e.g. 'gAAA' => '100000000000000000000'
	private static String base64ToBits(String validFor) {
        if (String.isEmpty(validFor)) {
            return '';
        }

		String validForBits = '';

		for (Integer i = 0; i < validFor.length(); i++) {
			String thisChar = validFor.mid(i, 1);
			Integer val = BASE_64_CHARS.indexOf(thisChar);
			String bits = decimalToBinary(val).leftPad(6, '0');
			validForBits += bits;
		}

		return validForBits;
	}

    //Wrapper class

    public class PicklistValue {
        @AuraEnabled
        public Boolean active { get; set; }
        @AuraEnabled
        public Boolean defaultValue { get; set; }
        @AuraEnabled
        public String label { get; set; }
        @AuraEnabled
        public String validFor { get; set; }
        @AuraEnabled
        public String value { get; set; }
        
        @AuraEnabled
        public List<PickListValue> dependents {get; set;}
        
        public PicklistValue(){}
        
        public PicklistValue(Boolean active, Boolean defaultValue, String label, String validFor, String value) {
            this.active = active;
            this.defaultValue = defaultValue;
            this.label = label;
            this.validFor = validFor;
            this.value = value;
        }

        public PicklistValue(Boolean active, Boolean defaultValue, String label, String value) {
            this.active = active;
            this.defaultValue = defaultValue;
            this.label = label;
            this.validFor = validFor;
            this.value = value;
        }

        public PicklistValue(String label, String value) {
            this.label = label;
            this.value = value;
        }

    }

}