public without sharing class MetaDataUtility {

    public static List<Metadata.LayoutSection> GetRecordTypePageLayout(string record_type_id,string objectType){
        
        Map<string,object> mso = null;
        System.debug('rerord 6' + record_type_id + ':' + objectType);
        string layout_name = GetRecordTypePageLayoutName(record_type_id,objectType,UserInfo.getProfileId());
        System.debug('layout 8' + layout_name);

        List<Metadata.LayoutSection>  temp =  GetLayoutSections(objectType,layout_name);
        List<Metadata.LayoutSection>  layoutSectionList = new List<Metadata.LayoutSection>();
        for(Metadata.LayoutSection section : temp){
            boolean a = false;
            for( Metadata.LayoutColumn c: section.layoutColumns){
                //system.debug(c);
                if(c.layoutItems != null && c.layoutItems.size() > 0 ){
                    a = true;
                }
                
            }
            if(a){
				layoutSectionList.add(section);             
            }
        }
        return layoutSectionList;
    }
    
    /*[{
            "attributes": {  
                "type": "Layout",
                "url": "/services/data/v53.0/tooling/sobjects/Layout/00h10000009iAb5AAE"
            },
            "Id": "00h10000009iAb5AAE",
            "Name": ".客户人员レイアウト",
            "TableEnumOrId": "01I10000000er3hEAA",
            "LayoutType": "Standard"
        }]
     */ 
    
    public static string GetTableOrEnumId(string objectType){
        
        Map<string,object> mso = null;
        string resp = null;
        string table_or_enum_id = objectType;
        if(objectType.endsWith('__c')){
            resp = ToolingQuery('SELECT id,DeveloperName from CustomObject where DeveloperName =\''+objectType.replace('__c', '')+'\'');
            if(resp == null){
                system.debug('resp is not ok');
                return null;
            }else{
                mso = (Map<string,object>)Json.deserializeUntyped(resp);
                if(integer.valueOf(mso.get('size')) > 0){
                    table_or_enum_id =  string.valueOf(((Map<string,object>)(((List<object>)mso.get('records'))[0])).get('Id')); 
                }else{
                    system.debug('no records');
                	return null;
                }
            }
        }
        System.debug('mso 60' + mso);

        return table_or_enum_id;
    }
    
    public static List<object> GetAllPageLayout(string objectType){
        string resp = null;
        Map<string,object> mso = null;
        
        
        string table_or_enum_id =  GetTableOrEnumId(objectType);
        
        if(string.isBlank(table_or_enum_id)){
            return new List<object>();
        }
        
        resp = ToolingQuery('SELECT id,name,TableEnumOrId,LayoutType  FROM Layout where TableEnumOrId = \''+table_or_enum_id+'\'');
        if(resp == null){
            system.debug('Layout where TableEnumOrId='+table_or_enum_id+' is null');
            return null;
        }else{
            mso = (Map<string,object>)Json.deserializeUntyped(resp);
            if(integer.valueOf(mso.get('size')) > 0){
                return (List<object>)mso.get('records');
            }else{
                system.debug('no records');
                return new List<object>();
            }
        }
    }
    
    
    public static string GetRecordTypePageLayoutName(string record_type_id,string objectType, string profile_id){
		System.debug('objectType 92' + objectType);
        System.debug('profile 93 ' + profile_id);
        
        if(!string.isBlank(objectType)){
            List<sobject> lso = [SELECT Id, Name, DeveloperName, SobjectType, IsActive, Description, BusinessProcessId FROM RecordType where SobjectType = :objectType];
            if(lso.size()==0){
                return string.valueOf(((Map<string,object>)(GetAllPageLayout(objectType)[0])).get('Name'));
            }
        }
        
        // 01210000000QfWdAAK
        string query = 'SELECT Layout.Name, Layout.TableEnumOrId, ProfileId, Profile.Name, RecordTypeId FROM ProfileLayout where id!=null ';
        if(!string.isBlank(record_type_id)){
            query += ' and RecordTypeId = \''+record_type_id+'\'';
        }
        
        if(!string.isBlank(objectType)){
            query += ' and TableEnumOrId = \''+ GetTableOrEnumId(objectType) +'\'';
        }
        
        if(!string.isBlank(profile_id)){
            query += ' and ProfileId = \''+profile_id+'\'';
        }
        query += ' order by LastModifiedDate desc ';
        system.debug('query='+query);
        string s = ToolingQuery(query);
        if(string.isBlank(s)){
            system.debug('s is blank');
            return null;
        }else{
            Map<string,object> mso = (Map<string,object>)JSON.deserializeUntyped(s);
            System.debug('mso 122' + mso);
        
            if(integer.valueOf(mso.get('size')) > 0){
                List<object> records = ((List<object>)mso.get('records'));
            
                mso = (Map<string,object>)(records[0]);
                return string.valueOf(((Map<string,object>)(mso.get('Layout'))).get('Name'));
            }else{
                return null;
            }
        }
        
        
        
    }
    
    public static string ToolingQuery(string query){
        
        system.debug('query='+query);
        String baseURL = 'callout:SF_Rest_API/services/data/v41.0/tooling/query?q='+ query.replace(' ', '+');
        HttpResponse resp = null;
        HttpRequest req = new HttpRequest();         
        req.setMethod('GET');
        
        //req.setHeader('Authorization', 'Bearer ' + UserInfo.getsessionid()); 
        //req.setEndpoint(baseURL); 
        req.setEndpoint(baseURL); 
        
        Http client = new Http();    
        resp = client.send(req);
        
        system.debug(resp.getStatus());
        system.debug(resp.getStatusCode());
        if(resp.getStatus() == 'OK'){
            string s = resp.getBody();
            system.debug(resp.getBody());
        	return s;
        }else{
            system.debug('status is not ok,error:'+resp.getBody());
            return null;
        }
        
    }
    
    public static List<Metadata.LayoutSection> GetLayoutSections(string object_name, string layout_name){
        List<String> componentNameList = new List<String>{object_name+'-'+layout_name};
        //通过Metadata.Operations.retrieve获取metadata
        //Metadata.Layout -> Metadata.LayoutSection -> Metadata.LayoutColumn objects -> Metadata.LayoutItem objects
        System.debug('componentNameList 171: ' + componentNameList);
        List<Metadata.Metadata> componentList = Metadata.Operations.retrieve(Metadata.MetadataType.Layout, componentNameList);
        System.debug('componentList 173 ' + componentList);
        if(componentList?.size() > 0){
            Metadata.Layout layout = (Metadata.Layout) componentList.get(0);
            List<Metadata.LayoutSection> layoutSectionList = layout.layoutSections;
            return layoutSectionList;
        }
        else{
            return null;
        }
        
    }
}