/**
 * @param province  省
 * @param salesDpt  本部
 * @param text 項目
 * @param cond 条件
 * @param val  値
 * @param search  値
 * @param t1 d | k
 * @param t2 all | null     全部展开
 * @param ocm 0 | null(1)      是否销售本部
 * @param mk 表示週
 * @param md 表示日
 */
public with sharing class PersonalCalendarController {
    // ユーザー上限
    private static Integer MAX_USER = 200;
    // 翻訳
    public static Map<String, String> at2CnMap;
    static {
        at2CnMap = new Map<String, String>();
        at2CnMap.put('病院', '用户拜访');
        at2CnMap.put('販売店', '经销商支持');
        at2CnMap.put('社内活動', '公司工作');
        at2CnMap.put('社外イベント', '社外会议');
        at2CnMap.put('移動', '移动');
        at2CnMap.put('休暇', '休假');
    }
    public static Map<String, String> mvlCnMap;
    static {
        mvlCnMap = new Map<String, String>();
        mvlCnMap.put('内視鏡室', '内镜室');
        mvlCnMap.put('手術室', '手术室');
        mvlCnMap.put('設備課', '设备科');
        mvlCnMap.put('外来', '门诊');
        mvlCnMap.put('病棟', '病房');
        mvlCnMap.put('その他', '其他');
    }
    public static Map<String, String> purposeCnMap;
    static {
        purposeCnMap = new Map<String, String>();
        purposeCnMap.put('移動', '移动');
        purposeCnMap.put('会議参加', '会议参加');
        purposeCnMap.put('休暇', '休假');
        purposeCnMap.put('点検', '点检');
        purposeCnMap.put('投诉対応(含QIS）', '投诉对应(含QIS)');
        purposeCnMap.put('納品(装机)', '装机');
    }
    private static Boolean isWeek;
    public Boolean getIsWeek() {
        return PersonalCalendarController.isWeek;
    }
    public Boolean t2 { get; set; }
    public Boolean ocmUser { get; set; }
    public Boolean allProvince { get; set; }

    // 登陆用户、検索条件に兼用
    public User loginUser { get; set; }

    // 本部、中国仕様
    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; }
    
    // 職位のチェックボックス、中国仕様
    String[] postNames = new String[]{};
    public String[] getPostNames() {
        return postNames;
    }
    public void setPostNames(String[] postNames) {
        this.postNames = postNames;
    }
    public static List<SelectOption> postOpts { get; private set; }
    static {
        postOpts = new List<SelectOption>();
        postOpts.add(new SelectOption('一般','一般'));
        postOpts.add(new SelectOption('高级','高级'));
        postOpts.add(new SelectOption('主管','主管'));
        postOpts.add(new SelectOption('副经理','副经理'));
        postOpts.add(new SelectOption('经理','经理'));
        postOpts.add(new SelectOption('副部长','副部长'));
        postOpts.add(new SelectOption('部长','部长'));
    }

    // 表示日
    public Date mdDay { get; private set; }
    public String getMdDayFormat() {
        return mdDay.format();
    }
    private Date mdToday; // 今週の場合 mdToday に値をセット
    // 表示範囲の日 yyyy-MM-dd or 時間 HH24
    public static List<String> mdKeyList;
    public static List<Map<String, String>> mdKeyList2 { get; private set; }    // 0indexに User

    // 表示ユーザー一覧
    public UserCalendarInfo campaignInfo { get; private set; }
    public Integer getCampaignMaxTr () {
        return campaignInfo.maxTr;
    }
    public List<Id> userIds { get; private set; }
    public Map<Id, UserCalendarInfo> userCalendarInfoMap { get; private set; }
    public static Map<Id, Daily_Report__c> drMap;
    public static Map<Id, Account> evtAccountMap;
    public static Map<Id, Campaign> evtCampaignMap;

    // 検索条件
    public static List<SelectOption> textOpts { get; private set; }
    static {
        textOpts = new List<SelectOption>();
        textOpts.add(new SelectOption('','-无-'));
        textOpts.add(new SelectOption('S:Alias', 'User'));
        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));
        textOpts.add(new SelectOption('S:Group__c', Schema.SObjectType.User.fields.Group__c.label));
        textOpts.add(new SelectOption('S:Category6__c', Schema.SObjectType.User.fields.Category6__c.label));
        textOpts.add(new SelectOption('S:SP_incharge_staff__c', Schema.SObjectType.User.fields.SP_incharge_staff__c.label));
        textOpts.add(new SelectOption('S:Sales_Speciality__c', Schema.SObjectType.User.fields.Sales_Speciality__c.label));
        textOpts.add(new SelectOption('S:Product_specialist_incharge_product__c', Schema.SObjectType.User.fields.Product_specialist_incharge_product__c.label));
//        textOpts.add(new SelectOption('S:Location', Schema.SObjectType.Event.fields.Location.label));
//        textOpts.add(new SelectOption('S:Subject', Schema.SObjectType.Event.fields.Subject.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 String searchText { get; set; }
    public static Integer markCnt { get; private set; }
//zzm 20231026 start
    public String weekPlanId { get; set;}
    public String preweekPlanId { get; set;}
    public String monthPlanId { get; set;}
    public String promotPlanId { get; set;}
    public String servePlanId { get; set;}
//zzm 20231026 end
    public PersonalCalendarController() {
//        Apexpages.currentPage().getHeaders().put('X-UA-Compatible', 'IE=8');
        PersonalCalendarController.markCnt = 0;
        evtListsMapMap = new Map<String, Map<String, List<Event>>>();
        evtMarkedMapMap = new Map<String, Map<String, List<Integer>>>();
        searchWordsMapMap = new Map<String, Map<String, List<String>>>();
        whatIdsMapMap = new Map<String, Map<String, List<Id>>>();
        // Dailyの時だけ使う、重ね表示用
        evtsStartMap = new Map<String, List<Long>>();
        evtsEndMap = new Map<String, List<Long>>();
        evtsZMap = new Map<String, List<Integer>>();
        
        provinceOpts = new List<SelectOption>();
        provinceOpts.add(new SelectOption('','--无--'));
    }

    // 画面初始化
    public Pagereference init() {
        // 当前用户信息、初期値にする
        if (loginUser == null) {
            loginUser = [Select Id, Salesdepartment__c, Province__c, ProfileId, Job_Category__c, UserRoleId, UserRole.Name, Additional_Role__c, Province_select__c, pe_tab_range__c From User where Id = :Userinfo.getUserId()];
        }
        salesDpt = loginUser.Salesdepartment__c;
        String jobCategory = loginUser.Job_Category__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));
                }
            }
        }

        // zzm 20230602 change hardcold start---
        //本周计划ID
        List<Report> report1 = [select id from Report where name='本周计划' limit 1];
        if(report1.size()>0) {
            weekPlanId = report1[0].id;
        }
        //上周报告明细id
        List<Report> report2 = [select id from Report where name like '%上周报告明细%' limit 1];
        if(report2.size()>0) {
            preweekPlanId = report2[0].id;
        }
        //月别计划ID
        List<Report> report3 = [select id from Report where name='月别计划实施情况' limit 1];
        if(report3.size()>0) {
            monthPlanId = report3[0].id;
        }
        
        //推广仪表板ID 
        List<Dashboard> dashboard1 = [select id from Dashboard where Title like '%KPI仪表板%' limit 1];
        if(dashboard1.size()>0) {
            promotPlanId = dashboard1[0].id;
        }
        
        //服务仪表盘ID
        List<Dashboard> dashboard = [select id from Dashboard where Title ='售后服务管理仪表板' limit 1];
        if(dashboard.size()>0) {
            servePlanId = dashboard[0].id;
        }
        

        // zzm 20230602 change hardcold end---

        PersonalCalendarController.isWeek = true;
        String mkParam = System.currentPageReference().getParameters().get('mk');
        if (String.isBlank(mkParam)) {
            // 现在日
            mdDay = Date.today();
        } else {
            String[] mkParams = mkParam.split('/');
            mdDay = Date.newInstance(Integer.valueOf(mkParams[0]), Integer.valueOf(mkParams[1]), Integer.valueOf(mkParams[2]));
        }
        String mdParam = System.currentPageReference().getParameters().get('md');
        if (String.isBlank(mdParam) == false) {
            PersonalCalendarController.isWeek = false;
            String[] mdParams = mdParam.split('/');
            mdDay = Date.newInstance(Integer.valueOf(mdParams[0]), Integer.valueOf(mdParams[1]), Integer.valueOf(mdParams[2]));
        }
        
        List<Date> mdateKeys = new List<Date>();            // sql用
        PersonalCalendarController.mdKeyList = new List<String>();
        PersonalCalendarController.mdKeyList2 = new List<Map<String, String>>();
        PersonalCalendarController.mdKeyList2.add(new Map<String, String>{'md' => 'User', 'md2' => 'User', 'mdCss' => ''});
        if (PersonalCalendarController.isWeek) {
            // 初始化，週単位
            mdDay = mdDay.toStartofWeek();
            Datetime dt = DateTime.newInstance(mdDay.year(), mdDay.month(), mdDay.day());
            String dayOfWeek = dt.format('EEEE'); //returns Sunday or Monday or ..
            if  (dayOfWeek == 'Monday') {
                mdDay = mdDay.addDays(-1);
            }
            Date weekStart = mdDay;
            for (Integer i = 0; i < 7; i++) {
                mdateKeys.add(weekStart);
                dt = DateTime.newInstance(weekStart.year(), weekStart.month(), weekStart.day());
                PersonalCalendarController.mdKeyList.add(dt.format('yyyy-MM-dd'));
                String mdCss = '';
                if (i == 0) mdCss = ' fc-sun';
                if (i == 1) mdCss = ' fc-mon';
                if (i == 2) mdCss = ' fc-tue';
                if (i == 3) mdCss = ' fc-wed';
                if (i == 4) mdCss = ' fc-thu';
                if (i == 5) mdCss = ' fc-fri';
                if (i == 6) mdCss = ' fc-sat';
                if (weekStart == System.Today()) { mdCss += ' fc-today'; mdToday = System.Today(); }
                PersonalCalendarController.mdKeyList2.add(new Map<String, String>{'md' => dt.format('yyyy-MM-dd'), 'md2' => dt.format('MM/dd'), 'mdCss' => mdCss});
                weekStart = weekStart.addDays(1);
            }
        } else {
            // 初始化，日単位
            mdateKeys.add(mdDay);
            String t2Param = System.currentPageReference().getParameters().get('t2');
            Integer hStart = 7;
            Integer hEnd = 21;
            if (t2Param == 'all') {
                hStart = 0;
                hEnd = 24;
                t2 = true;
            }
            for (Integer i = hStart; i < hEnd; i++) {
                PersonalCalendarController.mdKeyList.add('' + i + ':00');
                PersonalCalendarController.mdKeyList2.add(new Map<String, String>{'md' => '' + i + ':00', 'md2' => '' + i + ':00', 'mdCss' => ''});
            }
        }
        
        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];
        List<User> userList = [select Id from user where IsActive = true and Test_staff__c = false and UserType__c != 'PowerCustomerSuccess' 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 = '';
        }
        
        // 20150911 xudan 全部省
        allProvince = true;
        String ap = System.currentPageReference().getParameters().get('ap');
        if (ap == '0') {
            allProvince = false;
        } else if (ap == '1') {
            allProvince = true;
        } else {}
        // 省、省優先
        String provinceParam = System.currentPageReference().getParameters().get('province');
        if (String.isBlank(provinceParam)) {
            // loginUserの値を使う
        } else {
            loginUser.Province__c = provinceParam;
            province = provinceParam;
        }
        if (String.isBlank(loginUser.Province__c) == false) {
            salesDpt = '';
        }
        
        String text0;           // 隠し条件
        String cond0;           // 隠し条件
        String val0;            // 隠し条件
        String value1;          // 隠し条件
        // 20150511 xudan CIC 00154733
        // 職種にて销售市场/销售推广/销售服务/支援の場合には、デフォルトで販売本部のフラグがＯＮ。それ以外の場合にはＯＦＦ
        ocmUser = false;
        String ocmParam = System.currentPageReference().getParameters().get('ocm');
        if (ocmParam == '0') {
            ocmUser = false;
        } else if (ocmParam == '1') {
            ocmUser = true;
        } else {
            if (jobCategory == '销售推广' || jobCategory == '销售服务' || jobCategory == '销售市场' || jobCategory == '支援') {
                ocmUser = true;
            }
        }
        text1 = System.currentPageReference().getParameters().get('text');
        cond1 = System.currentPageReference().getParameters().get('cond');
        val1 = System.currentPageReference().getParameters().get('val');
        value1 = val1;
        searchText = System.currentPageReference().getParameters().get('search');
//      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:Location' && text1 != 'S:Subject') {
            users = this.getUserList(userList, text0, cond0, val0, text1, cond1, value1);
        } else {
            users = this.getUserList(userList, text0, cond0, val0);
        }
        if (users.size() > MAX_USER) {
	//zzm 20231026 start
            Apexpages.addMessage(new Apexpages.Message(Apexpages.Severity.WARNING, '用户超过' + MAX_USER + '人，请追加条件'));
	//zzm 20231026 end
        }
        userIds = new List<Id>();
        userCalendarInfoMap = new Map<Id, UserCalendarInfo>();
        for (User u : users) {
		//zzm 20231026 start
            userCalendarInfoMap.put(u.Id, new UserCalendarInfo(u.Id, u.Photo_Text__c,u.SmallPhotoUrl, u.Alias, u.Job_category_for_calendar__c));
            //zzm 20231026 end
	    userIds.add(u.Id);
        }
        
        List<Event> events = new List<Event>();
        List<Id> whatIdsForSearch = new List<Id>();
        List<Id> whatId_csForSearch = new List<Id>();
        events = this.getEventList(mdateKeys, userIds);
        for (Event e : events) {
            if (String.isBlank(e.WhatId) == false) {
                whatIdsForSearch.add(e.WhatId);
            }
            if (String.isBlank(e.WhatId__c) == false) {
                whatId_csForSearch.add(e.WhatId__c);
            }
            //zzm 230908 start 处理event主题为空时显示null 问题
            if (String.isBlank(e.Subject)) {
                e.Subject = '';
            }
            //zzm 230908 end 处理event主题为空时显示null 问题
        }
        // Mark イベント
        PersonalCalendarController.evtAccountMap = new Map<Id, Account>([
                Select Id, Name, Name_for_Daily_Report_text__c, HP_146POCM_Category_From_Dept__c
                  from Account where Id IN :whatId_csForSearch
        ]);
        PersonalCalendarController.evtCampaignMap = new Map<Id, Campaign>([
                Select Id, Name, Name2__c
                  from Campaign where Id IN :whatId_csForSearch
        ]);
        
        for (Event e : events) {
            UserCalendarInfo uci = userCalendarInfoMap.get(e.OwnerId);
            uci.addEvent(e, searchText);
        }
        PersonalCalendarController.drMap = ControllerUtil.reportMapSelectByIds(whatIdsForSearch);
        
        // キャンペーン情報
        campaignInfo = new UserCalendarInfo('0', '','', Schema.SObjectType.Campaign.Label, null);
        for (Campaign c :
                [select Id, StartDate, EndDate, RecordType.Name, Name, Name2__c, Society_Type__c, Status
                   from Campaign
                  where Status <> '草案中'
                    and StartDate <=: mdateKeys[mdateKeys.size() - 1]
                    and EndDate >=: mdateKeys[0]
                  order by Society_Type__c, StartDate
                ]
        ) {
            campaignInfo.addCampaign(c);
        }
        return null;
    }
    
    private List<Event> getEventList(List<Date> mdates, List<Id> users) {
        return getEventList(mdates, users, null, null, null);
    }
    
    private List<Event> getEventList(List<Date> mdates, List<Id> users, String txt, String con, String val) {
        String soql = 'select id, ActivityDate, OwnerId, Subject, WhatId__c, Location, Activity_Type2__c, whatId,'
                    + ' StartDateTime, DurationInMinutes, EndDateTime, Main_Visit_Location__c, IsScheduled__c, Purpose_Type__c,'
                    + ' Related_Opportunity1__c, Related_Opportunity1_ID__c, Related_Service1__c, Related_Service1_ID__c'
                    + ' from Event where WS_flg__c = false and ActivityDate IN :mdates and OwnerId IN :users'
                    // 任务事件改善 20210625 Start
                    + ' and EventStatus__c not in (\'04 取消\',\'05 延期\',\'06 关闭\',\'07 未执行\')';
                    // 任务事件改善 20210625 End
        soql += makeTextSql(txt, con, val);
        
        soql += ' order by OwnerId, StartDateTime, DurationInMinutes Desc, id';
        
        system.debug('=====' + soql);
        
        return ControllerUtil.eventSelectByUsers(soql, mdates, users);
    }
    
    private List<User> getUserList(List<User> userList, String txt, String con, String val) {
        return getUserList(userList, txt, con, val, null, null, null);
    }
    // ユーザの検索、TODO public で共通かする？
    private List<User> getUserList(List<User> userList, String txt, String con, String val, String txt1, String con1, String val1) {
        String soql = 'select Id, Photo_Text__c,SmallPhotoUrl, Salesdepartment__c, Province__c, Alias, Job_Category__c, Job_category_for_calendar__c'
                    + '  from User where Id in :userList and IsActive = true and Test_staff__c = false';
        // 全部省の場合
        if (allProvince == true) {
            List<String> provinces = new List<String>();
            if (String.isBlank(loginUser.Province_select__c) == false) {
                provinces = loginUser.Province_select__c.split(';', -1);
            } else {
                provinces.add(loginUser.Province__c);
            }
            soql += ' and Province__c in :provinces';
        } else {
            // 省を指定したら、本部を見ない
            if (!String.isBlank(loginUser.Province__c)) {
                soql += ' and Province__c = \'' + loginUser.Province__c + '\'';
            }
            else if (!String.isBlank(salesDpt) && salesDpt != '0') {
                soql += ' and Salesdepartment__c = \'' + salesDpt + '\'';
            }
        }
        
        soql += makeTextSql(txt, con, val);
        soql += makeTextSql(txt1, con1, val1);
        
        // 職位条件
//        if (postNames.size() > 0) {
//            soql += ' and (';
//            for (Integer i = 0; i < postNames.size(); i++) {
//                if (i == postNames.size() - 1) {
//                    soql += ' Post__c = \'' + postNames[i] + '\'';
//                } else {
//                    soql += ' Post__c = \'' + postNames[i] + '\' or';
//                }
//            }
//            soql += ')';
//        }
//        soql += ' order by Salesdepartment__c, Province__c, UserRole.Name';
        soql += ' order by Alias limit ' + (MAX_USER + 1);
        
        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 getSearchJsUrl() {
        PageReference pr = System.currentPageReference();
        String orgT = pr.getParameters().get('text');
        String orgC = pr.getParameters().get('cond');
        String orgV = pr.getParameters().get('val');
        String orgH = pr.getParameters().get('search');
        String orgO = pr.getParameters().get('ocm');
        String orgA = pr.getParameters().get('ap');
        pr.getParameters().put('text', null);
        pr.getParameters().put('cond', null);
        pr.getParameters().put('val', null);
        pr.getParameters().put('search', null);
        pr.getParameters().put('ocm', null);
        pr.getParameters().put('ap', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('text', orgT);
        pr.getParameters().put('cond', orgC);
        pr.getParameters().put('val', orgV);
        pr.getParameters().put('search', orgH);
        pr.getParameters().put('ocm', orgO);
        pr.getParameters().put('ap', orgA);
        return rtn;
    }
    // 検索用url
    public String getShowDayAllUrl() {
        PageReference pr = System.currentPageReference();
        String orgT = pr.getParameters().get('t2');
        String orgH = pr.getParameters().get('search');
        pr.getParameters().put('t2', null);
        pr.getParameters().put('search', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('t2', orgT);
        pr.getParameters().put('search', orgH);
        return rtn;
    }
    // 本部と省のURL
    public String getProvinceUrl() {
        PageReference pr = System.currentPageReference();
        String orgP = pr.getParameters().get('province');
        String orgS = pr.getParameters().get('salesDpt');
        String orgA = pr.getParameters().get('ap');
        pr.getParameters().put('province', null);
        pr.getParameters().put('salesDpt', null);
        pr.getParameters().put('ap', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('province', orgP);
        pr.getParameters().put('salesDpt', orgS);
        pr.getParameters().put('ap', orgA);
        return rtn;
    }
    public String getDayViewUrl() {
        PageReference pr = System.currentPageReference();
        String orgD = pr.getParameters().get('md');
        String orgK = pr.getParameters().get('mk');
        String orgH = pr.getParameters().get('search');
        pr.getParameters().put('mk', null);
        pr.getParameters().put('search', null);
        if (mdToday != null) {
            pr.getParameters().put('md', mdToday.format());
        } else {
            pr.getParameters().put('md', mdDay.format());
        }
        String rtn = pr.getUrl();
        pr.getParameters().put('md', orgD);
        pr.getParameters().put('mk', orgK);
        pr.getParameters().put('search', orgH);
        return rtn;
    }
    public String getWeekViewUrl() {
        PageReference pr = System.currentPageReference();
        String orgD = pr.getParameters().get('md');
        String orgK = pr.getParameters().get('mk');
        String orgH = pr.getParameters().get('search');
        pr.getParameters().put('md', null);
        pr.getParameters().put('mk', mdDay.format());
        pr.getParameters().put('search', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('md', orgD);
        pr.getParameters().put('mk', orgK);
        pr.getParameters().put('search', orgH);
        return rtn;
    }
    public String getChangeDayUrl() {
        PageReference pr = System.currentPageReference();
        String orgD = pr.getParameters().get('md');
        String orgK = pr.getParameters().get('mk');
        String orgH = pr.getParameters().get('search');
        pr.getParameters().put('md', null);
        pr.getParameters().put('mk', null);
        pr.getParameters().put('search', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('md', orgD);
        pr.getParameters().put('mk', orgK);
        pr.getParameters().put('search', orgH);
        return rtn;
    }
    public String getPrevUrl() {
        PageReference pr = System.currentPageReference();
        String orgD = pr.getParameters().get('md');
        String orgK = pr.getParameters().get('mk');
        String orgH = pr.getParameters().get('search');
        if (PersonalCalendarController.isWeek) {
            pr.getParameters().put('mk', mdDay.addDays(-7).format());
            pr.getParameters().put('md', null);
        } else {
            pr.getParameters().put('mk', null);
            pr.getParameters().put('md', mdDay.addDays(-1).format());
        }
        pr.getParameters().put('search', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('md', orgD);
        pr.getParameters().put('mk', orgK);
        pr.getParameters().put('search', orgH);
        return rtn;
    }
    public String getNextUrl() {
        PageReference pr = System.currentPageReference();
        String orgD = pr.getParameters().get('md');
        String orgK = pr.getParameters().get('mk');
        String orgH = pr.getParameters().get('search');
        if (PersonalCalendarController.isWeek) {
            pr.getParameters().put('mk', mdDay.addDays(7).format());
            pr.getParameters().put('md', null);
        } else {
            pr.getParameters().put('mk', null);
            pr.getParameters().put('md', mdDay.addDays(1).format());
        }
        pr.getParameters().put('search', null);
        String rtn = pr.getUrl();
        pr.getParameters().put('md', orgD);
        pr.getParameters().put('mk', orgK);
        pr.getParameters().put('search', orgH);
        return rtn;
    }

    // {ユーザーId単位 => {md2 => [XXX]}}
    public static Map<String, Map<String, List<Event>>> evtListsMapMap;
    public static Map<String, Map<String, List<Integer>>> evtMarkedMapMap;
    public static Map<String, Map<String, List<String>>> searchWordsMapMap;
    public static Map<String, Map<String, List<Id>>> whatIdsMapMap;     // getMdKeyList3 専用
    // Dailyの時だけ使う、重ね表示用
    public static Map<String, List<Long>> evtsStartMap;
    public static Map<String, List<Long>> evtsEndMap;
    public static Map<String, List<Integer>> evtsZMap;

    /**
     * 1人１つインスタンス
     */
    class UserCalendarInfo {
        public String userId { get; private set; }
        public String Photo_Text { get; private set; }
	//zzm 20231026 start
        public String Photo_F { get; private set; }
	//zzm 20231026 end
        public String userAlias { get; private set; }
        public String userDesc { get; private set; }
        // ユーザー毎、一週間のうち日の最大のエベント数
        public Integer maxTr { get; private set; }      // １つセルに最大Event数
        
        // Innerで使うprivate method
        private String at2Css(String at2) {
            String at2Css = 'fc-event';     // default
            if (at2 == '用户拜访') { at2Css = 'fc-eventH'; }
            else if (at2 == '经销商支持') { at2Css = 'fc-eventA'; }
            else if (at2 == '公司工作') { at2Css = 'fc-eventI'; }
            else if (at2 == '社外会议') { at2Css = 'fc-eventC'; }
            else if (at2 == '移动') { at2Css = 'fc-eventM'; }
            else if (at2 == '休假') { at2Css = 'fc-eventY'; }
            return at2Css;
        }
        
        // 訪問場所のIdを返す（Acount, Campaign の可能性があります）、ない場合 false を返す
        private String vfWhatIdC(String whatIdc) {
            String accId = 'false';
            if (String.isBlank(whatIdc) == false) {
                Account acc = PersonalCalendarController.evtAccountMap.get(whatIdc);
                Campaign cpg = PersonalCalendarController.evtCampaignMap.get(whatIdc);
                if (acc != null) {
                    accId = whatIdc;
                }
                if (cpg != null) {
                    accId = whatIdc;
                }
            }
            return accId;
        }
        
        private String time2Str(Event e) {
            String time2Str = '' + e.StartDateTime.hour();
            if (e.StartDateTime.minute() != 0) {
                time2Str += ':' + e.StartDateTime.format('mm');
            }
            time2Str += '-' + e.EndDateTime.hour();
            if (e.EndDateTime.minute() != 0) {
                time2Str += ':' + e.EndDateTime.format('mm');
            }
            return time2Str;
        }

        // VFより呼び出すpublic method
        public Integer getRowspan() {
            if (PersonalCalendarController.isWeek) {
                return maxTr == 0 ? 1 : maxTr;
            } else {
                return 1;
            }
        }

        public List<Map<String, String>> getMdKeyList3() {
            if (this.userId == '0') {
                return PersonalCalendarController.mdKeyList2;
            }
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.userId);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.userId);

            List<Map<String, String>> rtn2 = new List<Map<String, String>>();
            Map<String, String> md2User = PersonalCalendarController.mdKeyList2[0].clone();
            rtn2.add(md2User);
            if (PersonalCalendarController.isWeek) {
                for (Integer i = 1; i < PersonalCalendarController.mdKeyList2.size(); i++) {
                    Map<String, String> md2 = PersonalCalendarController.mdKeyList2[i].clone();
                    List<Id> whatIds = whatIdsMap.get(md2.get('md'));
                    List<Event> evtLists = evtListsMap.get(md2.get('md'));
System.debug('getMdKeyList3 mdKey:' + md2.get('md'));
System.debug('getMdKeyList3 WhatId.size():' + whatIds.size());
                    if (evtLists.size() > 0) {
                        Boolean submited = false;
                        for (Id whatId : whatIds) {
                            if (PersonalCalendarController.drMap.get(whatId) != null) {
                                Daily_Report__c dr = PersonalCalendarController.drMap.get(whatId);
System.debug('getMdKeyList3 ' + whatId + ':' + dr.Submit_Date_New__c);
                                if (dr.Submit_Date_New__c != null) {
                                    submited = true;
                                    break;
                                }
                            }
                        }
                        // TODO cssの調整がうまくいかないため、とりあえず 前の md2 に mdCssを設定
                        Map<String, String> md2Before = rtn2[rtn2.size() - 1];
                        if (submited == false) {
                            md2Before.put('mdCss', md2Before.get('mdCss') + ' unSubmited');
                        }
                    }
                    rtn2.add(md2);
                }
            } else {
                Boolean submited = false;
                Integer evtCnt = 0;
                for (Integer i = 1; i < PersonalCalendarController.mdKeyList2.size(); i++) {
                    Map<String, String> md2 = PersonalCalendarController.mdKeyList2[i].clone();
                    List<Id> whatIds = whatIdsMap.get(md2.get('md'));
                    List<Event> evtLists = evtListsMap.get(md2.get('md'));
                    if (evtLists.size() > 0) {
                        evtCnt += evtLists.size();
                        Boolean needBreakAll = false;
                        for (Id whatId : whatIds) {
                            if (PersonalCalendarController.drMap.get(whatId) != null) {
                                Daily_Report__c dr = PersonalCalendarController.drMap.get(whatId);
                                if (dr.Submit_Date_New__c != null) {
                                    submited = true;
                                    needBreakAll = true;
                                    break;
                                }
                            }
                        }
                        if (needBreakAll) break;
                    }
                }
                // 日の場合ユーザーに css をつける
                if (evtCnt > 0 && submited == false) {
                    md2User.put('mdCss', md2User.get('mdCss') + ' unSubmited');
                }
                for (Integer i = 1; i < PersonalCalendarController.mdKeyList2.size(); i++) {
                    Map<String, String> md2 = PersonalCalendarController.mdKeyList2[i].clone();
                    rtn2.add(md2);
                }
            }
            return rtn2;
        }

        // 週の行単位に変換、line は 1 から
        // maxTrが1以上の場合のみ呼び出す
        public List<List<Map<String, String>>> getRowInfoList() {
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.userId);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.userId);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.userId);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.userId);
            // Dailyの時だけ使う、重ね表示用
            List<Long> evtsStart = evtsStartMap.get(this.userId);
            List<Long> evtsEnd = evtsEndMap.get(this.userId);
            List<Integer> evtsZ = evtsZMap.get(this.userId);

            List<List<Map<String, String>>> trList = new List<List<Map<String, String>>>();
            for (Integer line = 1; line <= maxTr; line++) {
                List<Map<String, String>> tdList = new List<Map<String, String>>();
                trList.add(tdList);
                for (String mdKey : PersonalCalendarController.mdKeyList) {
                    List<Id> whatIds = whatIdsMap.get(mdKey);
                    List<Event> evtLists = evtListsMap.get(mdKey);
                    List<Integer> evtMarked = evtMarkedMap.get(mdKey);
                    List<String> searchWords = searchWordsMap.get(mdKey);
                    Map<String, String> ev = new Map<String, String>();
                    ev.put('isEvent', '0');
                    ev.put('evtId', '');
                    Integer sz = evtLists.size();
                    if (sz < line) {
                        // td のみ出力
                    } else {
                        ev.put('whatId', 'false');
                        for (Id whatId : whatIds) {
                            if (PersonalCalendarController.drMap.get(whatId) != null) {
                                ev.put('whatId', whatId);
                                break;
                            }
                        }
                        ev.put('isEvent', '1');
                        Event e = evtLists[line - 1];
                        ev.put('at2Css', at2Css(e.Activity_Type2__c));
                        ev.put('evtMarked', '' + evtMarked[line - 1]);
                        if (e.IsAllDayEvent) {
                            // Campaign
                            ev.put('evtId', e.NextEventC_ID__c);
                            if (PersonalCalendarController.isWeek) {
                                Integer lft = Date.valueOf(mdKey).daysBetween(e.ActivityDate);
System.debug('IsAllDayEvent Campaign lft:' + lft);
                                if (lft > 0) {
                                    ev.put('sLeft', (lft / 0.07) + '%');
                                } else {
                                    ev.put('sLeft', '0%');
                                }
                                Integer wth = Date.valueOf(e.ActivityDate).daysBetween(Date.newInstance(e.EndDateTime.year(), e.EndDateTime.month(), e.EndDateTime.day()));
                                ev.put('eWidth', ((wth + 1) / 0.07) + '%');
                            } else {
                                ev.put('sLeft', '0%');
                                ev.put('eWidth', '100%');
                            }
                            ev.put('time', e.Subject);
                            ev.put('title', e.Location);
                        } else {
                            // 週 Event
                            ev.put('evtId', e.Id);
                            ev.put('sLeft', '0%');
                            ev.put('eWidth', '100%');
                            ev.put('time', time2Str(e) + ' ' + e.Subject);
                            ev.put('title', String.isBlank(e.Location) ? e.Activity_Type2__c : e.Location);
                        }
                        ev.put('isScheduled', '' + e.IsScheduled__c);
                        ev.put('accId', vfWhatIdC(e.WhatId__c));
                        // 詳細の時使う
                        ev.put('mainVisit', e.Main_Visit_Location__c);
                        ev.put('purposeType', e.Purpose_Type__c);
                        ev.put('opp1Id', String.isBlank(e.Related_Opportunity1_ID__c) ? 'false' : e.Related_Opportunity1_ID__c);
                        ev.put('opp1Name', String.isBlank(e.Related_Opportunity1__c) ? '' : e.Related_Opportunity1__c);
                        ev.put('service1Id', String.isBlank(e.Related_Service1_ID__c) ? 'false' : e.Related_Service1_ID__c);
                        ev.put('service1Name', String.isBlank(e.Related_Service1__c) ? '' : e.Related_Service1__c);
                        ev.put('searchWord', searchWords[line - 1]);
                    }
                    tdList.add(ev);
                }
            }
            return trList;
        }

        // 日行単位に変換、TODO とりあえず 常に１行
        // mdKey の td常に 出力
        // Page側Eventが複数のevだけ再度loopする
        public List<List<Map<String, String>>> getDayEventInfoList() {
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.userId);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.userId);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.userId);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.userId);
            // Dailyの時だけ使う、重ね表示用
            List<Long> evtsStart = evtsStartMap.get(this.userId);
            List<Long> evtsEnd = evtsEndMap.get(this.userId);
            List<Integer> evtsZ = evtsZMap.get(this.userId);

            List<List<Map<String, String>>> tdList = new List<List<Map<String, String>>>();
            Integer evtIdx = 0;
            for (Integer mdIdx = 0; mdIdx < PersonalCalendarController.mdKeyList.size(); mdIdx++) {
                String mdKey = PersonalCalendarController.mdKeyList[mdIdx];
                List<Map<String, String>> evList = new List<Map<String, String>>();
                tdList.add(evList);
                List<Id> whatIds = whatIdsMap.get(mdKey);
                List<Event> evtLists = evtListsMap.get(mdKey);
                List<Integer> evtMarked = evtMarkedMap.get(mdKey);
                List<String> searchWords = searchWordsMap.get(mdKey);
                
                if (evtLists.size() > 0) {
                    for (Integer line = 1; line <= evtLists.size(); line++) {
                        Map<String, String> ev = new Map<String, String>();
                        ev.put('whatId', 'false');
                        for (Id whatId : whatIds) {
                            if (PersonalCalendarController.drMap.get(whatId) != null) {
                                ev.put('whatId', whatId);
                                break;
                            }
                        }
                        ev.put('isEvent', '1');
                        Event e = evtLists[line - 1];
                        ev.put('evtId', e.Id);
                        ev.put('at2Css', at2Css(e.Activity_Type2__c));
                        ev.put('evtMarked', '' + evtMarked[line - 1]);
System.debug('getDayEventInfoList evtsZ[' + evtIdx + ']=' + evtsZ[evtIdx]);
                        ev.put('sTop', '' + (evtsZ[evtIdx] * 4));       // 重なってずれの対応、top:4px ズラす
                        // 精度を保つため、ここ 0.6 にしました。
                        ev.put('sLeft', ((mdIdx * 100.0 + e.StartDateTime.minute() / 0.6) / PersonalCalendarController.mdKeyList.size()) + '%');
                        ev.put('eWidth', ((e.DurationInMinutes / 0.6) / PersonalCalendarController.mdKeyList.size()) + '%');
                        ev.put('isScheduled', '' + e.IsScheduled__c);
                        ev.put('time', (String.isBlank(e.Subject) ? e.StartDateTime.format('mm') + '-' + e.EndDateTime.format('mm') : e.Subject));
                        ev.put('time2', time2Str(e) + ' ' + e.Subject);
                        ev.put('title', String.isBlank(e.Location) ? e.Activity_Type2__c : e.Location);
                        ev.put('accId', vfWhatIdC(e.WhatId__c));
                        // 詳細の時使う
                        ev.put('mainVisit', e.Main_Visit_Location__c);
                        ev.put('purposeType', e.Purpose_Type__c);
                        ev.put('opp1Id', String.isBlank(e.Related_Opportunity1_ID__c) ? 'false' : e.Related_Opportunity1_ID__c);
                        ev.put('opp1Name', String.isBlank(e.Related_Opportunity1__c) ? '' : e.Related_Opportunity1__c);
                        ev.put('service1Id', String.isBlank(e.Related_Service1_ID__c) ? 'false' : e.Related_Service1_ID__c);
                        ev.put('service1Name', String.isBlank(e.Related_Service1__c) ? '' : e.Related_Service1__c);
                        ev.put('searchWord', searchWords[line - 1]);
                        evList.add(ev);
                        evtIdx++;
                    }
                } else {
                    // td のみ出力
                    Map<String, String> ev = new Map<String, String>();
                    ev.put('isEvent', '0');
                    ev.put('evtId', '');
                    ev.put('mainVisit', '');
                    evList.add(ev);
                }
            }
            return tdList;
        }
        
        // Instance 及び 中身 を作る関数
	//zzm 20231026 start
        public UserCalendarInfo(String userId, String Photo_Text,String Photo_F ,String userAlias, String userDesc) {
            this.userId = userId;
            this.Photo_Text = Photo_Text;
            this.Photo_F = Photo_F;
	    //zzm 20231026 end
            this.userAlias = userAlias;
            this.userDesc = userDesc;

            PersonalCalendarController.evtListsMapMap.put(this.userId, new Map<String, List<Event>>());
            PersonalCalendarController.evtMarkedMapMap.put(this.userId, new Map<String, List<Integer>>());
            PersonalCalendarController.searchWordsMapMap.put(this.userId, new Map<String, List<String>>());
            PersonalCalendarController.whatIdsMapMap.put(this.userId, new Map<String, List<Id>>());
            // Dailyの時だけ使う、重ね表示用
            PersonalCalendarController.evtsStartMap.put(this.userId, new List<Long>());
            PersonalCalendarController.evtsEndMap.put(this.userId, new List<Long>());
            PersonalCalendarController.evtsZMap.put(this.userId, new List<Integer>());
            
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.userId);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.userId);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.userId);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.userId);
            maxTr = 0;
            for (String mdKey : PersonalCalendarController.mdKeyList) {
                evtListsMap.put(mdKey, new List<Event>());
                evtMarkedMap.put(mdKey, new List<Integer>());
                searchWordsMap.put(mdKey, new List<String>());
                whatIdsMap.put(mdKey, new List<Id>());
            }
        }

        public void addEvent(Event e, String searchText) {
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.userId);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.userId);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.userId);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.userId);
            // Dailyの時だけ使う、重ね表示用
            List<Long> evtsStart = evtsStartMap.get(this.userId);
            List<Long> evtsEnd = evtsEndMap.get(this.userId);
            List<Integer> evtsZ = evtsZMap.get(this.userId);

System.debug('addEvent e.Id, searchText:' + e.Id + ',' + searchText);
            Datetime ead = e.StartDateTime;
            if (PersonalCalendarController.isWeek) {
                ead = DateTime.newInstance(e.ActivityDate.year(), e.ActivityDate.month(), e.ActivityDate.day());
            }
            String mdKey = ead.format('H') + ':00';
            if (PersonalCalendarController.isWeek) {
                mdKey = ead.format('yyyy-MM-dd');
            }
System.debug('addEvent mdKey:' + mdKey);
            List<Id> whatIds = whatIdsMap.get(mdKey);
            if (whatIds == null) {
                // 表示範囲外の場合
                return;
            }
            if (String.isBlank(e.WhatId) == false) {
System.debug('addEvent WhatId:' + e.WhatId);
                whatIds.add(e.WhatId);
            }

            List<Event> evtLists = evtListsMap.get(mdKey);
            evtLists.add(e);
            List<Integer> evtMarked = evtMarkedMap.get(mdKey);
            List<String> searchWords = searchWordsMap.get(mdKey);
            String mainVisit = e.Main_Visit_Location__c == null ? '' : e.Main_Visit_Location__c;
            mainVisit = PersonalCalendarController.mvlCnMap.containsKey(mainVisit) ? PersonalCalendarController.mvlCnMap.get(mainVisit) : mainVisit;
            e.Main_Visit_Location__c = mainVisit;
            String purposeType = e.Purpose_Type__c == null ? '' : e.Purpose_Type__c;
            purposeType = PersonalCalendarController.purposeCnMap.containsKey(purposeType) ? PersonalCalendarController.purposeCnMap.get(purposeType) : purposeType;
            e.Purpose_Type__c = purposeType;
            String searchWord = '';
            searchWord += String.isBlank(e.subject) ? '' : '｜｜' + e.subject;
            searchWord += String.isBlank(e.Location) ? '' : '｜｜' + e.Location;
            searchWord += String.isBlank(mainVisit) ? '' : '｜｜' + mainVisit;
            searchWord += String.isBlank(purposeType) ? '' : '｜｜' + purposeType;
            searchWord += String.isBlank(e.Related_Opportunity1__c) ? '' : '｜｜' + e.Related_Opportunity1__c;
            searchWord += String.isBlank(e.Related_Service1__c) ? '' : '｜｜' + e.Related_Service1__c;
            if (String.isBlank(e.WhatId__c) == false) {
                Account acc = PersonalCalendarController.evtAccountMap.get(e.WhatId__c);
                Campaign cpg = PersonalCalendarController.evtCampaignMap.get(e.WhatId__c);
                if (acc != null) {
                    searchWord += String.isBlank(acc.Name) ? '' : '｜｜' + acc.Name;
                    searchWord += String.isBlank(acc.Name_for_Daily_Report_text__c) ? '' : '｜｜' + acc.Name_for_Daily_Report_text__c;
                    searchWord += String.isBlank(acc.HP_146POCM_Category_From_Dept__c) ? '' : '｜｜' + acc.HP_146POCM_Category_From_Dept__c;
                }
                if (cpg != null) {
                    searchWord += String.isBlank(cpg.Name2__c) ? '' : '｜｜' + cpg.Name2__c;
                }
            }
            searchWord = searchWord.toUpperCase();
            searchWords.add(searchWord);
System.debug('addEvent searchWord:' + searchWord);
            
            Long evtStart =  e.StartDateTime.getTime();
            evtsStart.add(evtStart);
            evtsEnd.add(e.EndDateTime.getTime());
            Integer linkZ =  0;
            Integer evtZ =  0;
            if (evtsZ.size() > 0) {
                evtZ = evtsZ[evtsZ.size() - 1];
                linkZ = evtsZ[evtsZ.size() - 1];
            }
System.debug('addEvent evtStart:' + evtStart);
            for (Integer beforeIdx = evtsStart.size() - 2; beforeIdx >= 0; beforeIdx--) {
                Long bevtEnd =  evtsEnd[beforeIdx];
                Integer bevtZ =  evtsZ[beforeIdx];
System.debug('addEvent beforeIdx:' + beforeIdx);
System.debug('addEvent bevtEnd:' + bevtEnd);
System.debug('addEvent bevtZ:' + bevtZ);
                if (bevtEnd > evtStart) {
System.debug('addEvent bevtEnd > evtStart');
                    if (evtZ <= bevtZ) {
                        // 重なっているため、かつ 前のやつより階層Z小さい場合、一階下がる
System.debug('addEvent evtZ = bevtZ + 1');
                        evtZ = bevtZ + 1;
                        linkZ = bevtZ;
                    }
                } else {
                    if (linkZ != bevtZ) {
                        // さらに、階層も1階層以上離れた場合、同じ階層にする
                        if (evtZ - bevtZ >= 1) {
System.debug('addEvent evtZ = bevtZ');
                            evtZ = bevtZ;
                        }
                    }
                }
//                // 0 になったら、さらに遡る必要がないです。
//                if (evtZ == 0) {
//                    break;
//                }
            }
            evtsZ.add(evtZ);
System.debug('addEvent evtsZ.add:' + evtZ);

            String at2 = e.Activity_Type2__c == null ? '' : e.Activity_Type2__c;
            at2 = PersonalCalendarController.at2CnMap.containsKey(at2) ? PersonalCalendarController.at2CnMap.get(at2) : at2;
            e.Activity_Type2__c = at2;
            
            // Mark イベント
            Boolean isMark = false;
            if (String.isBlank(searchText) == false) {
                if (searchWord.indexOf(searchText.toUpperCase()) >= 0) {
                    isMark = true;
                }
            }
            if (isMark) {
                PersonalCalendarController.markCnt++;
                evtMarked.add(PersonalCalendarController.markCnt);
            } else {
                evtMarked.add(0);
            }
System.debug('addEvent evtMarked.add:' + isMark);
            if (evtLists.size() > maxTr) {
                maxTr = evtLists.size();
            }
        }
        
        public void addCampaign(Campaign c) {
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.userId);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.userId);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.userId);

System.debug('addCampaign c.Id:' + c.Id);
            String mdKey = PersonalCalendarController.mdKeyList[0];
System.debug('addCampaign mdKey:' + mdKey);
            List<Event> evtLists = evtListsMap.get(mdKey);
            List<Integer> evtMarked = evtMarkedMap.get(mdKey);
            List<String> searchWords = searchWordsMap.get(mdKey);
            Event e = new Event(
                IsAllDayEvent = true,           // getRowInfoList のところ Campaign かどうか 判断用
                NextEventC_ID__c = c.Id,
                Activity_Type2__c = '',
                Main_Visit_Location__c = '',
                Purpose_Type__c = '',
                Related_Opportunity1_ID__c = '',
                Related_Opportunity1__c = '',
                Related_Service1_ID__c = '',
                Related_Service1__c = '',
                IsScheduled__c = false,
                ActivityDate = c.StartDate,
                StartDateTime = DateTime.newInstance(c.StartDate.year(), c.StartDate.month(), c.StartDate.day()),
                EndDateTime = DateTime.newInstance(c.EndDate.year(), c.EndDate.month(), c.EndDate.day()),
                Subject = c.RecordType.Name + ':' + c.Society_Type__c
            );
            evtLists.add(e);
            if (PersonalCalendarController.isWeek) {
                e.Location = c.Name2__c;
            } else {
                e.Location = c.Name;
            }
            if (evtLists.size() > maxTr) {
                maxTr = evtLists.size();
            }
            // 使わない項目
            evtMarked.add(0);
            searchWords.add('');
        }
    }
}