/**
 * @param province  省
 * @param salesDpt  本部
 * @param text 項目
 * @param cond 条件
 * @param val  値
 * @param user 選択したUserId
 * @param tab  選択したtab名
 * @param ocm 0 | null(1)
 */
global with sharing class PersonalEvaluationController {
    // 个人评价信息
    public PersonalEvaluationInfo PEInfo { get; private set; }
    public static Personal_Evaluation__c pe99 { get; private set; }
    // カスタム設定
    public static Map<Integer, Personal_Evaluation__c> peSettingsMap { get; private set; }
    static {
        peSettingsMap = new Map<Integer, Personal_Evaluation__c> ();
        List<Personal_Evaluation__c> peList = Personal_Evaluation__c.getall().values();
        for (Personal_Evaluation__c pe : peList) {
            if (pe.IsProvince__c == true) continue;
            if (pe.IsActive__c == false) {
                if (pe.Tab_Index__c == 0) peSettingsMap.put(Integer.valueOf(pe.Tab_Index__c), pe);
                else continue;
            }
            peSettingsMap.put(Integer.valueOf(pe.Tab_Index__c), pe);
            if (pe.Tab_Index__c == 99) {
                pe99 = pe;
            }
        }
        System.debug('pe99 api:'+pe99.Api_Name__c);
    }
    
    // TabJS から カスタム設定を呼び出すときつかう
    @RemoteAction
    global static Map<String, Object> getPeSettings(String tabName, String toUserId) {
        Map<String, Object> rtn = new Map<String, Object>();
        String rtnStr = null;
        List<Personal_Evaluation__c> peList = Personal_Evaluation__c.getall().values();
        for(Personal_Evaluation__c pe : peList) {
            if (pe.IsProvince__c == true) continue;
            if (pe.Api_Name__c == tabName) {
                rtnStr = JSON.serialize(pe);
            }
        }
        if (String.isBlank(rtnStr) == false) {
            rtn = (Map<String, Object>) JSON.deserializeUntyped(rtnStr);
            
            // SMARMデータを検索
            String fromUserId = UserInfo.getUserId();
            if (toUserId == 'Nothing') toUserId = null;
            
            Schema.DescribeSobjectResult s = SMARM__c.sObjectType.getDescribe();
            Map<String, Schema.SObjectField> fieldMap = s.fields.getMap();
            List<SMARM__c> sList = ControllerUtil.getSmarmByUser(fieldMap, fromUserId, toUserId);
            
            if (sList.size() > 0) {
                Integer clipCnt = 0;
                Set<Object> reportNameSet = new Set<Object>();
                for (Integer i = 1; i <= Integer.valueOf(System.Label.SmarmClipNum); i++) {
                    String reportNameApi = 'ReportName' + i + '__c';
                    if (fieldMap.get(reportNameApi) != null && sList[0].get(reportNameApi) != null) {
                        clipCnt++;
                        reportNameSet.add(sList[0].get(reportNameApi));
                    }
                }
                // Clipした総件数を入れる
                rtn.put('ClipCnt', clipCnt);
                rtn.put('SmarmId', sList[0].Id);
                // PeSettingマップのReportNameがreportNameSetに存在するか
                for (String key : rtn.keySet()) {
                    // 念のため、Reportx_x_Name__cの項目だけを見る
                    if (key.startsWith('Report') && key.endsWith('Name__c')) {
                        if (reportNameSet.contains(rtn.get(key))) {
                            String clipKey = key.replace('Name__c', 'SmarmClip');
                            rtn.put(clipKey, 1);
                        }
                    }
                }
            }
        }
        return rtn;
    }

    public static Map<Integer, String> peSettingsMapHasIdx { get; private set; }
    static {
        peSettingsMapHasIdx = new Map<Integer, String>();
        for(Integer i = 1; i < 99; i++) {
            peSettingsMapHasIdx.put(i, 'false');
            if (peSettingsMap.get(i) != null) {
                peSettingsMapHasIdx.put(i, 'true');
            }
        }
    }
    public static String getPersonalEvaluationSettingJson() {
        return JSON.serialize(peSettingsMap);
    }
    public String selectedTab { get; set; }     // Tabのページ専用、initにて値をセット
    public Integer tabIdx { get; set; }         // InTabのページ専用、init2にて値をセット
    public Static Integer getFirstTabIdx() {
        for(Integer i = 1; i < 99; i++) {
            if (peSettingsMap.get(i) != null) {
                return i;
            }
        }
        return 0;
    }
    
    // 本部、中国仕様
    public String salesDpt { get; set; }
    public static List<SelectOption> salesDptOpts  { get; private set; }
    static {
        salesDptOpts = new List<SelectOption>();
        salesDptOpts.add(new SelectOption('','--无--'));
        salesDptOpts.add(new SelectOption('1.华北','1.华北'));
        salesDptOpts.add(new SelectOption('2.东北','2.东北'));
        salesDptOpts.add(new SelectOption('3.西北','3.西北'));
        salesDptOpts.add(new SelectOption('4.西南','4.西南'));
        salesDptOpts.add(new SelectOption('5.华东','5.华东'));
        salesDptOpts.add(new SelectOption('6.华南','6.华南'));
    }
    
    // 省、ユーザの省(在开发报表可以选择)を見る
    public String province { get; set; }
    public List<SelectOption> provinceOpts  { get; private set; }
    // 検索条件
    /*
    public static List<SelectOption> textOpts { get; private set; }
    static {
        textOpts = new List<SelectOption>();
        textOpts.add(new SelectOption('','-无-'));
        textOpts.add(new SelectOption('S:Post__c', Schema.SObjectType.User.fields.Post__c.label));
        textOpts.add(new SelectOption('S:Job_Category__c', Schema.SObjectType.User.fields.Job_Category__c.label));
    }
    public static List<SelectOption> equalOpts { get; private set; }
    static {
        equalOpts = new List<SelectOption>();
        equalOpts.add(new SelectOption('equals','等于'));
        equalOpts.add(new SelectOption('notequals','不等于'));
        equalOpts.add(new SelectOption('contains','包含'));
        equalOpts.add(new SelectOption('notcontains','不包含'));
    }
    public String text1 { get; set; }
    public String cond1 { get; set; }
    public String val1 { get; set; }
    */
    
    // 用户选择
    public List<SelectOption> userOpts { get; private set; }
    public String selectUser { get; set; }
    
    public Boolean ocmUser { get; set; }
    public Boolean leadUser { get; set; }

    // 登陆用户、検索条件に兼用
    public User loginUser { get; set; }
    public String peTabRange { get; private set; }
    
    // コメントして、Taskに残す
    @RemoteAction
    global static PersonalEvaluation__c saveComment(String userId, String recordTypeId, String subject, String comment, String base64Img, String tabName, String rptName, String rptNum) {
        // Tab Api NameからTab Nameを取得
        // タブ：subject = tabName、レポート：subject = rptName、よって
        String subjectMoji = subject;
        for (Personal_Evaluation__c pe : Personal_Evaluation__c.getall().values()) {
            if (pe.Api_Name__c == subject) {
                subjectMoji = pe.Name;
                break;
            }
        }
        Task tsk = new Task(
            OwnerId = userId,
            Subject = subjectMoji,
            Description = comment,
            ActivityDate = System.today()
        );
        
        PersonalEvaluation__c pec = null;
        if (String.isBlank(tabName)) {
            insert tsk;
            /*
            Document doc = new Document();
            // DeveloperNameをrandomに
            if (String.isBlank(base64Img) == false) {
                doc.Name = subjectMoji;
                doc.DeveloperName = 'pe_' + ControllerUtil.generateRandomStr(18);
                doc.Type = 'png';
                doc.Body = EncodingUtil.base64Decode(base64Img.removeStart('data:image/png;base64,'));
                ControllerUtil.createDocForEmail(new Document[]{doc});
            }
            */
            pec = new PersonalEvaluation__c(
                OwnerId = userId,
                RecordTypeId = recordTypeId,
                ReportName__c = subjectMoji,
                Comment__c = comment,
                Task_ID__c = tsk.Id,
                Graph1__c = String.isBlank(base64Img) ? null : '<img src=\"' + base64Img + '\"></img>'
            );
            
            insert pec;
            pec.ReportUrlText__c = '/apex/PersonalEvaluationReport?pecId=' + pec.Id;
            update pec;
            
            // 以前のロジックを保留
            if (String.isBlank(base64Img)) {
                tsk.ReportUrlText__c = pec.ReportUrlText__c;
            }
            // 新ロジック
            else {
                tsk.ReportUrlText__c = '/apex/PersonalEvaluationCommentImg?id=' + pec.Id;
            }
            tsk.PersonalEvaluation_ID__c = pec.Id;
        } else {
            insert tsk;
            /*
            Document doc = new Document();
            if (String.isBlank(base64Img) == false) {
                doc.Name = subjectMoji;
                doc.DeveloperName = 'pe_' + ControllerUtil.generateRandomStr(18);
                doc.Type = 'png';
                doc.Body = EncodingUtil.base64Decode(base64Img.removeStart('data:image/png;base64,'));
                ControllerUtil.createDocForEmail(new Document[]{doc});
            }
            */
            pec = new PersonalEvaluation__c(
                OwnerId = userId,
                RecordTypeId = recordTypeId,
                TabName__c = subjectMoji,
                Comment__c = comment,
                Task_ID__c = tsk.Id,
                Graph1__c = String.isBlank(base64Img) ? null : '<img src=\"' + base64Img + '\"></img>',
                ReportUrlText__c = tsk.ReportUrlText__c
            );
            insert pec;
            // 以前のロジックを保留
            if (String.isBlank(base64Img)) {
                tsk.ReportUrlText__c = '/apex/PersonalEvaluation?user=' + userId + '&tab=' + tabName;
            }
            // 新ロジック
            else {
                tsk.ReportUrlText__c = '/apex/PersonalEvaluationCommentImg?id=' + pec.Id;
            }
            tsk.PersonalEvaluation_ID__c = pec.Id;
        }
//        if (String.isBlank(base64Img) == false) {
//            Attachment attach = new Attachment(
//                contentType = 'image/png',
//                name = comment,
//                parentId = tsk.Id,
//                body = EncodingUtil.base64Decode(base64Img)
//            );
//            insert attach;
//        }
        update tsk;
        
        return pec;
    }
    
    // 20150729 xudan 個人評価の送信ロジック
    // saveCommentの時点で、画像はまだSFDCに保存されなかったから、メールに添付できません
    @RemoteAction
    global static void sendPeEmail(String pecId) {
        PersonalEvaluation__c pe = new PersonalEvaluation__c(
            Id = pecId,
            SendEmail__c = true
        );
        update pe;
    }
    
    // SMARMにデータ更新
    @RemoteAction
    global static Map<String, Object> upsertSmarm(String toUserId, String reportName, String imgData, Boolean checked) {
        Map<String, Object> rtn = new Map<String, Object>();
        
        String fromUserId = UserInfo.getUserId();
        if (toUserId == 'Nothing') toUserId = null;
        
        Schema.DescribeSobjectResult s = SMARM__c.sObjectType.getDescribe();
        Map<String, Schema.SObjectField> fieldMap = s.fields.getMap();
        List<SMARM__c> sList = ControllerUtil.getSmarmByUser(fieldMap, fromUserId, toUserId);
        SMARM__c smarm = new SMARM__c();
        // 更新
        if (sList.size() > 0) {
            //Map<String, Attachment> attMap = ControllerUtil.getSmarmAtts(sList[0].Id);
            Map<String, Attachment> attMap = new Map<String, Attachment>();
            for (Attachment att : ControllerUtil.getSmarmAtts(sList[0].Id)) {
                attMap.put(att.Name, att);
            }
            smarm.Id = sList[0].Id;
            smarm.Review_Practitioner__c = fromUserId;
            smarm.Review_Target__c = toUserId;
            
            Integer idx = 0;
            Integer clipCnt = 0;
            // reportNameでマッチ、動的対応
            for (Integer i = 1; i <= Integer.valueOf(System.Label.SmarmClipNum) ; i++) {
                String reportNameApi = 'ReportName' + i + '__c';
                if (fieldMap.get(reportNameApi) != null && sList[0].get(reportNameApi) != null) {
                    // 名前で見つかったら、必ず既存のものを削除
                    if (sList[0].get(reportNameApi) == reportName) {
                        // 画像を削除
                        smarm.put('Image' + i + '__c', null);
                        smarm.put('ReportName' + i + '__c', null);
                        smarm.put('Comment' + i + '__c', null);
                        clipCnt--;
                        idx = i;
                        // 添付ファイルも削除
                        if (attMap.containsKey(idx + '.' + reportName)) {
                            ControllerUtil.deleteAttachments(new Attachment[] {attMap.get(idx + '.' + reportName)});
                        }
                    }
                    clipCnt++;
                }
            }
            // 新画像を入れる
            if (idx == 0) {
                // 最大idxの画像APIをチェック
                for (Integer i = 1; i <= Integer.valueOf(System.Label.SmarmClipNum) ; i++) {
                    String imgApi = 'Image' + i + '__c';
                    if (fieldMap.get(imgApi) != null && sList[0].get(imgApi) == null) {
                        idx = i;
                        break;
                    }
                }
                smarm.put('Image' + idx + '__c', '<img src=\"' + imgData + '\"></img>');
                smarm.put('ReportName' + idx + '__c', reportName);
                // 添付ファイルを入れる
                Attachment att = new Attachment(
                    Name = idx + '.' + reportName,
                    ParentId = smarm.Id,
                    Body = EncodingUtil.base64Decode(imgData.removeStart('data:image/png;base64,')),
                    ContentType = 'image/png'
                );
                ControllerUtil.insertAttachments(new Attachment[] {att});
                
                clipCnt++;
            }
            //update smarm;
            ControllerUtil.upsertSMARM(smarm);
            
            rtn.put('SmarmId', smarm.Id);
            rtn.put('ClipCnt', clipCnt);
        }
        // 新規
        else {
            smarm.Review_Practitioner__c = fromUserId;
            smarm.Review_Target__c = toUserId;
            smarm.Image1__c = '<img src=\"' + imgData + '\"></img>';
            smarm.ReportName1__c = reportName;
            smarm.Status__c = 'Delete';
            // バッチユーザにする
            smarm.OwnerId = System.label.account_web_1;
            //insert smarm;
            ControllerUtil.upsertSMARM(smarm);
            
            rtn.put('SmarmId', smarm.Id);
            rtn.put('ClipCnt', 1);
            
            // Attachmentも追加
            Attachment att = new Attachment(
                Name = '1.' + reportName,
                ParentId = smarm.Id,
                Body = EncodingUtil.base64Decode(imgData.removeStart('data:image/png;base64,')),
                ContentType = 'image/png'
            );
            ControllerUtil.insertAttachments(new Attachment[] {att});
        }
        return rtn;
    }

    // MB のグラグを作成用
    @ReadOnly
    @RemoteAction
    global static String getJsonSAP(String dcName, String userId,String current_fiscalyear) {
        Personal_Evaluation__c pes = peSettingsMap.get(0);
        String sql_6_1 = pes.Report6_1_Sql__c;
        String sql_6_2 = pes.Report6_2_Sql__c;
        String sql_6_3 = pes.Report6_3_Sql__c;
        if (String.isBlank(dcName) == false) {
            sql_6_1 += ' and Opportunity_Category__c=:dcName';
            sql_6_2 += ' and GBIC__c=:dcName';
            sql_6_3 += ' and GBIC__c=:dcName';
        }
        List<AggregateResult> MB_Target = Database.query(sql_6_1 + (pes.Report6_1_Sql1__c == null ? '' : ' ' + pes.Report6_1_Sql1__c) + (pes.Report6_1_Sql2__c == null ? '' : ' ' + pes.Report6_1_Sql2__c));
        Map<String, Map<String, Double>> rtn = new Map<String, Map<String, Double>>();
        Map<String, Double> rtnTargetWt = new Map<String, Double>();
        Map<String, Double> rtnTargetNum = new Map<String, Double>();
        for(AggregateResult ar : MB_Target) {
            rtnTargetWt.put(String.valueOf(ar.get('GBIC')), ar.get('wt') == null ? 0 : Decimal.valueOf(String.valueOf(ar.get('wt'))));
            rtnTargetNum.put(String.valueOf(ar.get('GBIC')), ar.get('num') == null ? 0 : Decimal.valueOf(String.valueOf(ar.get('num'))));
        }
        List<AggregateResult> MB_Ship = Database.query(sql_6_2 + (pes.Report6_2_Sql1__c == null ? '' : ' ' + pes.Report6_2_Sql1__c) + (pes.Report6_2_Sql2__c == null ? '' : ' ' + pes.Report6_2_Sql2__c));
        Map<String, Double> rtnShipWt = new Map<String, Double>();
        Map<String, Double> rtnShipNum = new Map<String, Double>();
        for(AggregateResult ar : MB_Ship) {
            rtnShipWt.put(String.valueOf(ar.get('GBIC')), ar.get('wt') == null ? 0 : Decimal.valueOf(String.valueOf(ar.get('wt'))));
            rtnShipNum.put(String.valueOf(ar.get('GBIC')), ar.get('num') == null ? 0 : Decimal.valueOf(String.valueOf(ar.get('num'))));
        }
        List<AggregateResult> MB_BackOrder = Database.query(sql_6_3 + (pes.Report6_3_Sql1__c == null ? '' : ' ' + pes.Report6_3_Sql1__c) + (pes.Report6_3_Sql2__c == null ? '' : ' ' + pes.Report6_3_Sql2__c));
        Map<String, Double> rtnBackOrderWt = new Map<String, Double>();
        Map<String, Double> rtnBackOrderNum = new Map<String, Double>();
        for(AggregateResult ar : MB_BackOrder) {
            rtnBackOrderWt.put(String.valueOf(ar.get('GBIC')), ar.get('wt') == null ? 0 : Decimal.valueOf(String.valueOf(ar.get('wt'))));
            rtnBackOrderNum.put(String.valueOf(ar.get('GBIC')), ar.get('num') == null ? 0 : Decimal.valueOf(String.valueOf(ar.get('num'))));
        }
        rtn.put('Target_wt', rtnTargetWt);
        rtn.put('Ship_wt', rtnShipWt);
        rtn.put('BackOrder_wt', rtnBackOrderWt);
        rtn.put('Target_num', rtnTargetNum);
        rtn.put('Ship_num', rtnShipNum);
        rtn.put('BackOrder_num', rtnBackOrderNum);
        return JSON.serialize(rtn);
    }

    // MB注残(JsonMB_BackOrder) 订单数/未付款数/无用户合同书
    @ReadOnly
    @RemoteAction
    global static String getJsonMBSA(String dcName, String userId) {
        Personal_Evaluation__c pes = peSettingsMap.get(0);
        String sql_7_1 = pes.Report7_1_Sql__c;
        if (String.isBlank(dcName) == false) {
            sql_7_1 += ' and Opportunity_Category__c=:dcName';
        }
        Map<String, Double> rtn = new Map<String, Double>();
        List<AggregateResult> MB_SA = Database.query(sql_7_1 + (pes.Report7_1_Sql1__c == null ? '' : ' ' + pes.Report7_1_Sql1__c) + (pes.Report7_1_Sql2__c == null ? '' : ' ' + pes.Report7_1_Sql2__c));
        rtn.put('Order', MB_SA[0].get('Order') == null ? 0 : Decimal.valueOf(String.valueOf(MB_SA[0].get('Order'))));
        rtn.put('NClct', MB_SA[0].get('NClct') == null ? 0 : Decimal.valueOf(String.valueOf(MB_SA[0].get('NClct'))));
        rtn.put('NCtrc', MB_SA[0].get('NCtrc') == null ? 0 : Decimal.valueOf(String.valueOf(MB_SA[0].get('NCtrc'))));
        return JSON.serialize(rtn);
    }

    // MB询价 引合のステージ単位での件数 
    @ReadOnly
    @RemoteAction
    global static String getJsonForcast(String dcName, String userId) {
        Personal_Evaluation__c pes = peSettingsMap.get(0);
        String sql_7_3 = pes.Report7_3_Sql__c;
        if (String.isBlank(dcName) == false) {
            sql_7_3 += ' and Opportunity_Category__c=:dcName';
        }
        Map<String, Integer> rtn = new Map<String, Integer>();
        Date forcastDay;
        Date maxForcastDay;
        forcastDay = System.today();
        maxForcastDay = forcastDay.addMonths(6);    // TODO 年度末 ?
        maxForcastDay = Date.newInstance(maxForcastDay.year(), maxForcastDay.month(), 1);
        maxForcastDay = maxForcastDay.addDays(-1);
        List<Opportunity> mbList = Database.query(sql_7_3 + (pes.Report7_3_Sql1__c == null ? '' : ' ' + pes.Report7_3_Sql1__c) + (pes.Report7_3_Sql2__c == null ? '' : ' ' + pes.Report7_3_Sql2__c));
        if (mbList.size() > 0) {
//            forcastDay = mbList[0].Sales_forecast_day_BA__c;
//            forcastDay = Date.newInstance(forcastDay.year(), forcastDay.month(), 1);
//            maxForcastDay = mbList[mbList.size() - 1].Sales_forecast_day_BA__c;
//            maxForcastDay = Date.newInstance(maxForcastDay.year(), maxForcastDay.month(), 1);
            for (Opportunity mb : mbList) {
                Integer cnt = rtn.get(mb.Sales_forecast_YM_BA__c);
                if (cnt == null) {
                    cnt = 0;
                }
                cnt++;
                rtn.put(mb.Sales_forecast_YM_BA__c, cnt);
            }
        }
        // Listに変換
        List<Map<String, Integer>> rtnList = new List<Map<String, Integer>>();      // Map<String, Integer> には１つペアしかない
        while (forcastDay <= maxForcastDay) {
            String yyyymm = '' + forcastDay.year() * 100 + forcastDay.month();
            String ymKey = yyyymm.mid(2, 2) + '年' + yyyymm.right(2) + '月';
            Integer cnt = rtn.get(ymKey);
            if (cnt == null) {
                cnt = 0;
            }
            rtnList.add(new Map<String, Integer>{ymKey => cnt});
            forcastDay = forcastDay.addMonths(1);
        }
        return JSON.serialize(rtnList);
    }

    // MB のグラグを作成用
    @ReadOnly
    @RemoteAction
    global static String getJsonOppSum(String dcName, String userId) {
        // MB データの取得
        Personal_Evaluation__c pes = peSettingsMap.get(0);
        String sql_8_1 = pes.Report8_1_Sql__c;
        String sql_8_2 = pes.Report8_2_Sql__c;
        String sql_8_3 = pes.Report8_3_Sql__c;
        if (String.isBlank(dcName) == false) {
            sql_8_1 += ' and Opportunity_Category__c=:dcName';
            sql_8_2 += ' and Opportunity_Category__c=:dcName';
            sql_8_3 += ' and Opportunity_Category__c=:dcName';
        }
        List<AggregateResult> MB_Opp_Bid = Database.query(sql_8_1 + (pes.Report8_1_Sql1__c == null ? '' : ' ' + pes.Report8_1_Sql1__c) + (pes.Report8_1_Sql2__c == null ? '' : ' ' + pes.Report8_1_Sql2__c));
        List<AggregateResult> MB_Opp_Auth = Database.query(sql_8_2 + (pes.Report8_2_Sql1__c == null ? '' : ' ' + pes.Report8_2_Sql1__c) + (pes.Report8_2_Sql2__c == null ? '' : ' ' + pes.Report8_2_Sql2__c));
        List<AggregateResult> MB_Opp_A = Database.query(sql_8_3 + (pes.Report8_3_Sql1__c == null ? '' : ' ' + pes.Report8_3_Sql1__c) + (pes.Report8_3_Sql2__c == null ? '' : ' ' + pes.Report8_3_Sql2__c) + ' and Competitor__c = \'A\'');
        List<AggregateResult> MB_Opp_B = Database.query(sql_8_3 + (pes.Report8_3_Sql1__c == null ? '' : ' ' + pes.Report8_3_Sql1__c) + (pes.Report8_3_Sql2__c == null ? '' : ' ' + pes.Report8_3_Sql2__c) + ' and Competitor__c = \'B\'');
        List<AggregateResult> MB_Opp_C = Database.query(sql_8_3 + (pes.Report8_3_Sql1__c == null ? '' : ' ' + pes.Report8_3_Sql1__c) + (pes.Report8_3_Sql2__c == null ? '' : ' ' + pes.Report8_3_Sql2__c) + ' and Competitor__c = \'C\'');
        List<AggregateResult> MB_Opp_D = Database.query(sql_8_3 + (pes.Report8_3_Sql1__c == null ? '' : ' ' + pes.Report8_3_Sql1__c) + (pes.Report8_3_Sql2__c == null ? '' : ' ' + pes.Report8_3_Sql2__c) + ' and Competitor__c = \'D\'');
        List<AggregateResult> MB_Opp_E = Database.query(sql_8_3 + (pes.Report8_3_Sql1__c == null ? '' : ' ' + pes.Report8_3_Sql1__c) + (pes.Report8_3_Sql2__c == null ? '' : ' ' + pes.Report8_3_Sql2__c) + ' and Competitor__c = \'E\'');
        Map<String, Map<String, Double>> rtn = new Map<String, Map<String, Double>>();
        Map<String, Double> oppBid = new Map<String, Double>();
        oppBid.put('wt', MB_Opp_Bid[0].get('wt') == null     ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_Bid[0].get('wt'))));
        oppBid.put('num', MB_Opp_Bid[0].get('num') == null   ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_Bid[0].get('num'))));
        Map<String, Double> oppAuth = new Map<String, Double>();
        oppAuth.put('wt', MB_Opp_Auth[0].get('wt') == null   ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_Auth[0].get('wt'))));
        oppAuth.put('num', MB_Opp_Auth[0].get('num') == null ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_Auth[0].get('num'))));
        Map<String, Double> oppA = new Map<String, Double>();
        oppA.put('wt', MB_Opp_A[0].get('wt') == null         ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_A[0].get('wt'))));
        oppA.put('num', MB_Opp_A[0].get('num') == null       ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_A[0].get('num'))));
        Map<String, Double> oppB = new Map<String, Double>();
        oppB.put('wt', MB_Opp_B[0].get('wt') == null         ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_B[0].get('wt'))));
        oppB.put('num', MB_Opp_B[0].get('num') == null       ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_B[0].get('num'))));
        Map<String, Double> oppC = new Map<String, Double>();
        oppC.put('wt', MB_Opp_C[0].get('wt') == null         ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_C[0].get('wt'))));
        oppC.put('num', MB_Opp_C[0].get('num') == null       ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_C[0].get('num'))));
        Map<String, Double> oppD = new Map<String, Double>();
        oppD.put('wt', MB_Opp_D[0].get('wt') == null         ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_D[0].get('wt'))));
        oppD.put('num', MB_Opp_D[0].get('num') == null       ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_D[0].get('num'))));
        Map<String, Double> oppE = new Map<String, Double>();
        oppE.put('wt', MB_Opp_E[0].get('wt') == null         ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_E[0].get('wt'))));
        oppE.put('num', MB_Opp_E[0].get('num') == null       ? 0 : Decimal.valueOf(String.valueOf(MB_Opp_E[0].get('num'))));

        rtn.put('oppBid',  oppBid);
        rtn.put('oppAuth', oppAuth);
        rtn.put('oppA',    oppA);
        rtn.put('oppB',    oppB);
        rtn.put('oppC',    oppC);
        rtn.put('oppD',    oppD);
        rtn.put('oppE',    oppE);
        return JSON.serialize(rtn);
    }
    
    // 右側のlist、３つ
    public List<SObject> getR1InfoList() {
        String userId = selectUser;
        //List<SObject> rInfo = Database.query(pe99.Report1_1__c + (pe99.Report1_1_Column__c == null ? '' : ' ' + pe99.Report1_1_Column__c));
        List<SObject> rInfo = ControllerUtil.getPe99Info(pe99.Report1_1__c + (pe99.Report1_1_Column__c == null ? '' : ' ' + pe99.Report1_1_Column__c), userId);
        if (rInfo.size() == 0) {
            Schema.SObjectType targetType = Schema.getGlobalDescribe().get(getR1InfoTable());
            if (targetType != null) {
                rInfo.add(targetType.newSObject());
            }
        }
        return rInfo;
    }
    public List<String> getR1InfoColumnList() {
        String columnStr = pe99.Report1_1__c.toLowerCase();
        Integer st = columnStr.indexOf('select');
        Integer ed = columnStr.indexOf('from');
        columnStr = columnStr.substring(st + 6, ed);
        List<String> rtn = new List<String>();
        for (String col : columnStr.split(',')) {
            rtn.add(col.trim());
        }
        return rtn;
    }
    public String getR1InfoTable() {
        return getInfoTable(pe99.Report1_1__c.toLowerCase());
    }
    public List<SObject> getR2InfoList() {
        String userId = selectUser;
        //List<SObject> rInfo = Database.query(pe99.Report1_2__c + (pe99.Report1_2_Column__c == null ? '' : ' ' + pe99.Report1_2_Column__c));
        List<SObject> rInfo = ControllerUtil.getPe99Info(pe99.Report1_2__c + (pe99.Report1_2_Column__c == null ? '' : ' ' + pe99.Report1_2_Column__c), userId);
        if (rInfo.size() == 0) {
            Schema.SObjectType targetType = Schema.getGlobalDescribe().get(getR2InfoTable());
            if (targetType != null) {
                rInfo.add(targetType.newSObject());
            }
        }
        return rInfo;
    }
    public List<String> getR2InfoColumnList() {
        String columnStr = pe99.Report1_2__c.toLowerCase();
        Integer st = columnStr.indexOf('select');
        Integer ed = columnStr.indexOf('from');
        columnStr = columnStr.substring(st + 6, ed);
        List<String> rtn = new List<String>();
        for (String col : columnStr.split(',')) {
            rtn.add(col.trim());
        }
        return rtn;
    }
    public String getR2InfoTable() {
        return getInfoTable(pe99.Report1_2__c.toLowerCase());
    }
    public List<SObject> getR3InfoList() {
        String userId = selectUser;
        //List<SObject> rInfo = Database.query(pe99.Report1_3__c + (pe99.Report1_3_Column__c == null ? '' : ' ' + pe99.Report1_3_Column__c));
        List<SObject> rInfo = ControllerUtil.getPe99Info(pe99.Report1_3__c + (pe99.Report1_3_Column__c == null ? '' : ' ' + pe99.Report1_3_Column__c), userId);
        if (rInfo.size() == 0) {
            Schema.SObjectType targetType = Schema.getGlobalDescribe().get(getR3InfoTable());
            if (targetType != null) {
                rInfo.add(targetType.newSObject());
            }
        }
        return rInfo;
    }
    public List<String> getR3InfoColumnList() {
        String columnStr = pe99.Report1_3__c.toLowerCase();
        Integer st = columnStr.indexOf('select');
        Integer ed = columnStr.indexOf('from');
        columnStr = columnStr.substring(st + 6, ed);
        List<String> rtn = new List<String>();
        for (String col : columnStr.split(',')) {
            rtn.add(col.trim());
        }
        return rtn;
    }
    public String getR3InfoTable() {
        return getInfoTable(pe99.Report1_3__c.toLowerCase());
    }
    private String getInfoTable(String columnStr) {
        Integer st = columnStr.indexOf('from ');
        Integer ed = columnStr.indexOf(' ', st + 5);
        if (ed >= 0) {
            columnStr = columnStr.substring(st + 5, ed);
        } else {
            columnStr = columnStr.substring(st + 5);
        }
        return columnStr;
    }

    public PersonalEvaluationController() {
        //Apexpages.currentPage().getHeaders().put('X-UA-Compatible', 'IE=8');
        provinceOpts = new List<SelectOption>();
        provinceOpts.add(new SelectOption('','--无--'));
    }
    
    // 画面初始化(<apex:tabPanel>外側)
    public void init() {
        Boolean hasUrlParam = false;
        if (loginUser == null) {
            loginUser = [Select Id, Alias, Name, Post__c, Job_Category__c, UserRoleId, UserRole.Name, Additional_Role__c, Salesdepartment__c, Province__c, Province_select__c, pe_tab_range__c From User where Id = :Userinfo.getUserId()];
            peTabRange = loginUser.pe_tab_range__c;
        }
        salesDpt = loginUser.Salesdepartment__c;
        
        // 省プルダウンを作成、自分の省は選択できる、以外は項目を見る
        province = loginUser.Province__c;
        provinceOpts.add(new SelectOption(province, province));
        if (String.isBlank(loginUser.Province_select__c) == false) {
            for (String pro : loginUser.Province_select__c.split(';', -1)) {
                if (pro != province) {
                    provinceOpts.add(new SelectOption(pro, pro));
                }
            }
        }
        
        Set<Id> roleIds = ControllerUtil.getAllSubRoleIds(loginUser.UserRoleId, loginUser.Additional_Role__c);
        List<User> userList = [select Id from user where IsActive = true and Test_staff__c = false and UserRoleId in :roleIds];
        userList.add(loginUser);

        // 本部
        String salesDptParam = System.currentPageReference().getParameters().get('salesDpt');
        if (String.isBlank(salesDptParam)) {
            // loginUserの値を使う
        } else {
            salesDpt = salesDptParam;
            //loginUser.Province__c = '';
            province = '';
            hasUrlParam = true;
        }
        // 省、省優先
        String provinceParam = System.currentPageReference().getParameters().get('province');
        if (String.isBlank(provinceParam)) {
            // loginUserの値を使う
        } else {
            //loginUser.Province__c = provinceParam;
            province = provinceParam;
            hasUrlParam = true;
        }
        if (String.isBlank(province) == false) {
            salesDpt = '';
        }
        // 本部と省はBlankの場合、ユーザの省を見る
        if (salesDptParam == '0' && String.isBlank(provinceParam)) {
            province = loginUser.Province__c;
        }
        // tab
        String tabParam = System.currentPageReference().getParameters().get('tab');
System.debug('tabParam:' + tabParam);
        if (String.isBlank(tabParam)) {
            // Controllerの値をそのままつかう
            if (String.isBlank(selectedTab)) {
System.debug('selectedTab:' + selectedTab);
                selectedTab = peSettingsMap.get(getFirstTabIdx()).Api_Name__c;
System.debug('selectedTab:' + selectedTab);
            }
        } else {
            selectedTab = tabParam;
            hasUrlParam = true;
        }
        // user
        String userParam = System.currentPageReference().getParameters().get('user');
        if (String.isBlank(userParam)) {
            // 空白の値を使う
            selectUser = 'Nothing';
        } else {
            selectUser = userParam;
            User u = [select pe_tab_range__c from User where Id = :selectUser];
            peTabRange = u.pe_tab_range__c;
            hasUrlParam = true;
        }
        
        // ユーザー検索条件
        String text0;           // 隠し条件
        String cond0;           // 隠し条件
        String val0;            // 隠し条件
//        String value1;          // 隠し条件
        ocmUser = true;
        leadUser = true;
        String ocmParam = System.currentPageReference().getParameters().get('ocm');
        if (ocmParam == '0') {
            ocmUser = false;
        }
        String leadParam = System.currentPageReference().getParameters().get('lead');
        if (leadParam == '0') {
            leadUser = false;
        }
//        text1 = System.currentPageReference().getParameters().get('text');
//        cond1 = System.currentPageReference().getParameters().get('cond');
//        val1 = System.currentPageReference().getParameters().get('val');
//        value1 = val1;
//        if (String.isBlank(text1) == false) {
//            hasUrlParam = true;
//        }
//        if (text1 == 'S:Job_Category__c' && cond1 == 'equals') {
//            if (ocmUser) {
//                if (String.isBlank(value1)) {
//                    value1 = '销售推广,销售服务,销售市场,支援';
//                } else {
//                    value1 += ',销售推广,销售服务,销售市场,支援';
//                }
//            }
//        } else {
            if (ocmUser) {
                text0 = 'S:Job_Category__c';
                cond0 = 'equals';
                val0 = '销售推广,销售服务,销售市场';
            }
//        }
        
        List<User> users = new List<User>();
//        if (text1 == 'S:Alias' || text1 == 'S:Post__c' || text1 == 'S:Job_Category__c') {
//            users = this.getUserList(userList, text0, cond0, val0, text1, cond1, value1);
//        } else {
            users = this.getUserList(userList, text0, cond0, val0);
//        }
        userOpts = new List<SelectOption>();
        Map<Id, User> userMap = new Map<Id, User>();
        if (users.size() > 0) {
            for (User u : users) {
                userOpts.add(new SelectOption(u.Id, u.Alias + '　(' + u.Post__c + ',' + u.Job_Category__c + ',' + u.UserRole.Name + ')'));
                userMap.put(u.Id, u);
            }
            if (selectUser == 'Nothing' && userParam != 'Nothing') {
                // urlからパラメータ指定してない場合、自分のUserIdを設定する、自分は userOptsにいない場合、userOptsの先頭に追加
                if (userMap.containsKey(loginUser.Id) == false && hasUrlParam == false) {
                    selectUser = loginUser.Id;
                    userMap.put(loginUser.Id, loginUser);
                    userOpts.add(0, new SelectOption(loginUser.Id, loginUser.Alias + '　(' + loginUser.Post__c + ',' + loginUser.Job_Category__c + ',' + loginUser.UserRole.Name + ')'));
                } else {
                    selectUser = users[0].Id;
                }
            } else {
                if (userMap.containsKey(selectUser) == false) {
                    User selectedU = [Select Id, Alias, Name, Post__c, Job_Category__c, UserRoleId, UserRole.Name, Salesdepartment__c, Province__c From User where Id = :selectUser];
                    selectUser = selectedU.Id;
                    userMap.put(selectUser, selectedU);
                    userOpts.add(0, new SelectOption(selectedU.Id, selectedU.Alias + '　(' + selectedU.Post__c + ',' + selectedU.Job_Category__c + ',' + selectedU.UserRole.Name + ')'));
                }
            }
        } else {
            selectUser = 'Nothing';
        }
        
        if (selectUser != 'Nothing' && userMap.containsKey(selectUser)) {
            PEInfo = new PersonalEvaluationInfo(userMap.get(selectUser));
        } else {
            selectUser = 'Nothing';
            PEInfo = new PersonalEvaluationInfo();
        }
    }
    
    // 画面初始化(<apex:tabPanel>内側)
    public void init2() {
        // user
        String userParam = System.currentPageReference().getParameters().get('user');
        if (String.isBlank(userParam) || userParam == 'Nothing') {
            // 空白の値を使う
            selectUser = 'Nothing';
        } else {
            selectUser = userParam;
            loginUser = [Select Id, Alias, Name, Post__c, Job_Category__c, UserRoleId, UserRole.Name, Salesdepartment__c, Province__c, pe_tab_range__c From User where Id = :selectUser];
            peTabRange = loginUser.pe_tab_range__c;
            PEInfo = new PersonalEvaluationInfo(loginUser);
        }
        // tabIdx
        String tabIdxParam = System.currentPageReference().getParameters().get('tabIdx');
        if (String.isBlank(tabIdxParam)) {
            // Controllerの値をそのままつかう
        } else {
            tabIdx = Integer.valueOf(tabIdxParam);
            selectedTab = peSettingsMap.get(tabIdx).Api_Name__c;
        }
    }
    
    // ユーザの検索、TODO public で共通かする？
    private List<User> getUserList(List<User> userList, String txt, String con, String val) {
        return getUserList(userList, txt, con, val, null, null, null);
    }
    private List<User> getUserList(List<User> userList, String txt, String con, String val, String txt1, String con1, String val1) {
        String soql = 'select Id, Name, Salesdepartment__c, Province__c, Alias, Post__c, Job_Category__c, UserRole.Name '
                    + '  from User where Id in :userList and IsActive = true and Test_staff__c = false and usertype != \'PowerCustomerSuccess\' ';
        // 省を指定したら、本部を見ない
        if (!String.isBlank(province)) {
            soql += ' and Province__c = \'' + province + '\'';
        }
        else if (!String.isBlank(salesDpt) && salesDpt != '0') {
            soql += ' and Salesdepartment__c = \'' + salesDpt + '\'';
        }
        // 主管以下
        if (leadUser) {
            soql += ' and (Post__c = \'一般\' or Post__c = \'高级\' or Post__c = \'主管\')';
        }
        
        soql += makeTextSql(txt, con, val);
        soql += makeTextSql(txt1, con1, val1);
        
        soql += ' order by Alias ';
        
        system.debug('getUserList=====' + soql);
        
        return Database.query(soql);
    }
    
    private String makeTextSql(String txt1, String con, String val) {
        String soql = '';
        if (String.isBlank(con)) {
            con = 'equals';
        }
        // containsの場合、日報画面の病院検索を真似し、spaceで分けて、and検索
        // equalsの場合、SF標準の検索を真似し、「,」で分けて、or検索
        if (!String.isBlank(txt1)) {
            if ((con == 'contains' || con == 'notcontains') && val.contains(' ')) {
                String[] vals = val.split(' ');
                String cSql = '';
                for (String v : vals) {
                    cSql += this.makeTextSqlStr(txt1, con, v);
                }
                if (con == 'contains') {
                    soql += cSql;
                } else {
                    // notcontains
                    cSql = cSql.replaceAll(' and ', ') and (NOT ');
                    soql += cSql.substring(1) + ') ';
                }
            } else if ((con == 'equals' || con == 'notequals') && val.contains(',')) {
                String[] vals = val.split(',');
                if (vals.size() > 0) {
                    String txt = txt1.substring(2);     // S:Name 、最初の２文字がタイプです
                    soql += ' and ( ';
                    for (String v : vals) {
                        if (con == 'equals') {
                            soql += txt + ' = \'' + v + '\' or ';
                        } else {
                            // notequals
                            soql += txt + ' <> \'' + v + '\' and ';
                        }
                    }
                    soql = soql.substring(0, soql.length() - 4);
                    soql += ')';
                }
            } else {
                String cSql = this.makeTextSqlStr(txt1, con, val);
                if (con != 'notcontains') {
                    soql += this.makeTextSqlStr(txt1, con, val);
                } else {
                    // notcontains
                    if (!String.isBlank(cSql)) {
                        cSql = cSql.substring(5);       // ' and ' の5文字を外す
                        soql += ' and (NOT ' + cSql + ') ';
                    }
                }
            }
        }
        return soql;
    }
    
    /**
     * 文字列検索文を作成
     */ 
    private String makeTextSqlStr(String txt1, String con, String val) {
        String soql = '';
        if (!String.isBlank(txt1)) {
            String txt = txt1.substring(2);
            String colType = txt1.substring(0, 2);
            String tmpVal = val;
            // 空白の場合''にする
            if (String.isBlank(tmpVal)) {
                if (con == 'equals') {
                    //soql += ' and ' + txt + ' = ' + tmpVal;
                    soql += ' and ' + txt + ' = null';
                } else if (con == 'notequals') {
                    soql += ' and ' + txt + ' <> null';
                } else {
                    // 空白の場合、contains, notcontains と starts withは無視
                }
            } else {
                soql += ' and ' + txt;
                if (con == 'equals') {
                    if (colType == 'S:') {
                        soql += ' = \'' + tmpVal + '\'';
                    } else {
                        soql += ' = ' + tmpVal + ' ';
                    }
                } else if (con == 'notequals') {
                    if (colType == 'S:') {
                        soql += ' <> \'' + tmpVal + '\'';
                    } else {
                        soql += ' <> ' + tmpVal + ' ';
                    }
                } else if (con == 'contains' || con == 'notcontains') {
                    soql += ' like \'%' + tmpVal + '%\'';
                } else if (con == 'starts with') {
                    soql += ' like \'' + tmpVal + '%\'';
                } else {
                    if (colType == 'S:') {
                        soql += ' ' + con + '\'' + tmpVal + '\'';
                    } else {
                        soql += ' ' + con + ' ' + tmpVal + ' ';
                    }
                }
            }
        }
        return soql;
    }
    
    // 本部と省のURL
    public String getProvinceUrl() {
        PageReference pr = System.currentPageReference();
        String orgP = pr.getParameters().get('province');
        String orgS = pr.getParameters().get('salesDpt');
        String orgU = pr.getParameters().get('user');
        String orgB = pr.getParameters().get('tab');
        pr.getParameters().put('province', null);
        pr.getParameters().put('salesDpt', null);
        pr.getParameters().put('user', null);
        pr.getParameters().put('tab', selectedTab);
        String rtn = pr.getUrl();
        pr.getParameters().put('province', orgP);
        pr.getParameters().put('salesDpt', orgS);
        pr.getParameters().put('user', orgU);
        pr.getParameters().put('tab', orgB);
        return rtn;
    }
    
    // 検索用url
    public String getSearchJsUrl() {
        PageReference pr = System.currentPageReference();
        String orgT = pr.getParameters().get('text');
        String orgC = pr.getParameters().get('cond');
        String orgV = pr.getParameters().get('val');
        String orgU = pr.getParameters().get('user');
        String orgB = pr.getParameters().get('tab');
        String orgO = pr.getParameters().get('ocm');
        String orgL = pr.getParameters().get('lead');
        pr.getParameters().put('text', null);
        pr.getParameters().put('cond', null);
        pr.getParameters().put('val', null);
        pr.getParameters().put('user', null);
        pr.getParameters().put('tab', selectedTab);
        pr.getParameters().put('ocm', null);
        pr.getParameters().put('lead', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('text', orgT);
        pr.getParameters().put('cond', orgC);
        pr.getParameters().put('val', orgV);
        pr.getParameters().put('user', orgU);
        pr.getParameters().put('tab', orgB);
        pr.getParameters().put('ocm', orgO);
        pr.getParameters().put('lead', orgL);
        return rtn;
    }
    
    // 検索用url
    public String getUserUrl() {
        PageReference pr = System.currentPageReference();
        String orgU = pr.getParameters().get('user');
        String orgB = pr.getParameters().get('tab');
        pr.getParameters().put('user', null);
        pr.getParameters().put('tab', selectedTab);
        String rtn = pr.getUrl();
        pr.getParameters().put('user', orgU);
        pr.getParameters().put('tab', orgB);
        return rtn;
    }
    
    // 个人评价信息类
    class PersonalEvaluationInfo {
        public String txtName { get; private set; }
        public String txtId { get; private set; }
        
        public PersonalEvaluationInfo() {
            txtName = '';
            txtId = '';
        }
        // Id, Alias
        public PersonalEvaluationInfo(User u) {
            txtName = u.Alias;
            txtId = u.Id;
            txtId = txtId.substring(0, 15);
        }
    }
}