/**
 * @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 OFSCalendarController {
    // 翻訳
    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('納品(装机)', '装机');
    }
    
    public String accid {get; private set;}
    public String cid {get; private set;}
    public String oid {get; private set;}
    public String mid {get; private set;}
    public String loc {get; private set;}
    public String sub {get; private set;}
    public Boolean eventCreateFlg {get; private set;}
    public String closeFlg {get; private set;}
    
    public Boolean t2 { get; set; }

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

    // 本部、中国仕様
    public String salesDpt { get; set; }

    // 表示日
    public Date mdDay { get; private set; }
    public String getMdDayFormat() {
        return mdDay.format();
    }
    private Date mdToday; // 今週の場合 mdToday に値をセット
    // 表示範囲の日 yyyy-MM-dd or 時間 HH24
    public static Map<String, List<String>> mdKeyListMap;
    public static Map<String, List<Map<String, String>>> mdKeyList2Map { get; private set; }    // 0indexに User
    // 表示ユーザー一覧
    public WeekCalendarInfo campaignInfo { get; private set; }
    public Integer getCampaignMaxTr () {
        return campaignInfo.maxTr;
    }
    public List<String> weekKeyList { get; private set; }
    public Map<String, WeekCalendarInfo> weekCalendarInfoMap { get; private set; }
    public static Map<Id, Daily_Report__c> drMap;
    public static Map<Id, Account> evtAccountMap;
    public static Map<Id, Campaign> evtCampaignMap;
    
    public String searchText { get; set; }
    public static Integer markCnt { get; private set; }
    
    public OFSCalendarController() {
//        Apexpages.currentPage().getHeaders().put('X-UA-Compatible', 'IE=8');
        OFSCalendarController.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>>();
    }

    // 画面初始化
    public Pagereference init() {
        // 当前用户信息、初期値にする
        if (loginUser == null) {
            loginUser = [Select Id, Photo_Text__c, Salesdepartment__c, Province__c, Alias, Job_Category__c, Job_category_for_calendar__c, ProfileId From User where Id = :Userinfo.getUserId()];
        }
        salesDpt = loginUser.Salesdepartment__c;
        
        String mkParam = System.currentPageReference().getParameters().get('mk');
        
        accid = System.currentPageReference().getParameters().get('accid');
        cid = System.currentPageReference().getParameters().get('cid');
        oid = System.currentPageReference().getParameters().get('oid');
        mid = System.currentPageReference().getParameters().get('mid');
        sub = System.currentPageReference().getParameters().get('sub');
        loc = System.currentPageReference().getParameters().get('loc');
        
        
        //分开显示的仕様暂且不管，直接出‘+’
        //eventCreateFlg = false;
        //closeFlg = System.currentPageReference().getParameters().get('closeFlg');
        //if(!String.isBlank(closeFlg)){
        //  eventCreateFlg = true;
        //}
        //
        eventCreateFlg = true;
        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]));
        }
        List<Date> mdateKeys = new List<Date>();            // sql用
        OFSCalendarController.mdKeyListMap = new Map<String, List<String>>();
        OFSCalendarController.mdKeyList2Map = new Map<String, List<Map<String, String>>>();
        //OFSCalendarController.mdKeyList2.add(new Map<String, String>{'md' => 'User', 'md2' => 'User', 'mdCss' => ''});
        
        // 初始化，週単位
        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);
        }
        
        List<User> users = new List<User>();
        users.add(loginUser);

        weekKeyList = new List<String>();
        weekCalendarInfoMap = new Map<String, WeekCalendarInfo>();
        for (Integer i = 0; i < 4; i++) {
            weekKeyList.add(String.valueOf(mdDay.addDays(7*i)));
            List<String> mdKeyListTemp = new List<String>();
            List<Map<String, String>> mdKeyList2Temp = new List<Map<String, String>>();
            mdKeyList2Temp.add(new Map<String, String>{'md' => 'User', 'md2' => 'User', 'mdCss' => ''});
            Date weekStart = mdDay.addDays(7*i);
            for (Integer j = 0; j < 7; j++) {
                mdateKeys.add(weekStart);
                dt = DateTime.newInstance(weekStart.year(), weekStart.month(), weekStart.day());
                mdKeyListTemp.add(dt.format('yyyy-MM-dd'));
                String mdCss = '';
                if (Math.mod(j,7) == 0) mdCss = ' fc-sun';
                if (Math.mod(j,7) == 1) mdCss = ' fc-mon';
                if (Math.mod(j,7) == 2) mdCss = ' fc-tue';
                if (Math.mod(j,7) == 3) mdCss = ' fc-wed';
                if (Math.mod(j,7) == 4) mdCss = ' fc-thu';
                if (Math.mod(j,7) == 5) mdCss = ' fc-fri';
                if (Math.mod(j,7) == 6) mdCss = ' fc-sat';
                if (weekStart == System.Today()) { mdCss += ' fc-today'; mdToday = System.Today(); }
                mdKeyList2Temp.add(new Map<String, String>{'md' => dt.format('yyyy-MM-dd'), 'md2' => dt.format('MM/dd'), 'mdCss' => mdCss});
                weekStart = weekStart.addDays(1);
            }
            OFSCalendarController.mdKeyListMap.put(String.valueOf(mdDay.addDays(7*i)), mdKeyListTemp);
            OFSCalendarController.mdKeyList2Map.put(String.valueOf(mdDay.addDays(7*i)), mdKeyList2Temp);
            weekCalendarInfoMap.put(String.valueOf(mdDay.addDays(7*i)), new WeekCalendarInfo(String.valueOf(mdDay.addDays(7*i))));
        }
        
        /*
        weekKeyList.add(String.valueOf(mdDay));
        List<String> mdKeyLista = new List<String>();
        List<Map<String, String>> mdKeyList2a = new List<Map<String, String>>();
        Date weekStart = mdDay;
        for (Integer i = 0; i < 14; i++) {
            mdateKeys.add(weekStart);
            dt = DateTime.newInstance(weekStart.year(), weekStart.month(), weekStart.day());
            mdKeyList1.add(dt.format('yyyy-MM-dd'));
            String mdCss = '';
            if (Math.mod(i,7) == 0) mdCss = ' fc-sun';
            if (Math.mod(i,7) == 1) mdCss = ' fc-mon';
            if (Math.mod(i,7) == 2) mdCss = ' fc-tue';
            if (Math.mod(i,7) == 3) mdCss = ' fc-wed';
            if (Math.mod(i,7) == 4) mdCss = ' fc-thu';
            if (Math.mod(i,7) == 5) mdCss = ' fc-fri';
            if (Math.mod(i,7) == 6) mdCss = ' fc-sat';
            if (weekStart == System.Today()) { mdCss += ' fc-today'; mdToday = System.Today(); }
            mdKeyList2a.add(new Map<String, String>{'md' => dt.format('yyyy-MM-dd'), 'md2' => dt.format('MM/dd'), 'mdCss' => mdCss});
            weekStart = weekStart.addDays(1);
        }
        OFSCalendarController.mdKeyList2.put(String.valueOf(mdDay),mdKeyList2a);
        
        weekKeyList.add(String.valueOf(mdDay.addDays(7)));
        Date weekStart = mdDay.addDays(7);
        for (Integer i = 0; i < 14; i++) {
            mdateKeys.add(weekStart);
            dt = DateTime.newInstance(weekStart.year(), weekStart.month(), weekStart.day());
            OFSCalendarController.mdKeyList.add(dt.format('yyyy-MM-dd'));
            String mdCss = '';
            if (Math.mod(i,7) == 0) mdCss = ' fc-sun';
            if (Math.mod(i,7) == 1) mdCss = ' fc-mon';
            if (Math.mod(i,7) == 2) mdCss = ' fc-tue';
            if (Math.mod(i,7) == 3) mdCss = ' fc-wed';
            if (Math.mod(i,7) == 4) mdCss = ' fc-thu';
            if (Math.mod(i,7) == 5) mdCss = ' fc-fri';
            if (Math.mod(i,7) == 6) mdCss = ' fc-sat';
            if (weekStart == System.Today()) { mdCss += ' fc-today'; mdToday = System.Today(); }
            OFSCalendarController.mdKeyList2.add(new Map<String, String>{'md' => dt.format('yyyy-MM-dd'), 'md2' => dt.format('MM/dd'), 'mdCss' => mdCss});
            weekStart = weekStart.addDays(1);
        }
        
        weekCalendarInfoMap = new Map<String, WeekCalendarInfo>();
        weekCalendarInfoMap.put(String.valueOf(mdDay), new WeekCalendarInfo(String.valueOf(mdDay)));
        weekCalendarInfoMap.put(String.valueOf(mdDay.addDays(7)), new WeekCalendarInfo(String.valueOf(mdDay.addDays(7))));
        */
        
        List<Event> events = new List<Event>();
        List<Id> whatIdsForSearch = new List<Id>();
        List<Id> whatId_csForSearch = new List<Id>();
        events = this.getEventList(mdateKeys, users);
        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);
            }
        }
        // Mark イベント
        OFSCalendarController.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
        ]);
        
        
        OFSCalendarController.evtCampaignMap = new Map<Id, Campaign>([
                Select Id, Name, Name2__c
                  from Campaign where Id IN :whatId_csForSearch
        ]);
        
        for (Event e : events) {
            String eActDate = String.valueOf(e.ActivityDate.toStartofWeek());
            WeekCalendarInfo uci = weekCalendarInfoMap.get(eActDate);
            uci.addEvent(e, searchText);
        }
        OFSCalendarController.drMap = ControllerUtil.reportMapSelectByIds(whatIdsForSearch);
        
        return null;
    }
    
   
    private List<Event> getEventList(List<Date> mdates, List<User> users) {
        return getEventList(mdates, users, null, null, null);
    }
    
    private List<Event> getEventList(List<Date> mdates, List<User> 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';
                    
        soql += ' order by OwnerId, StartDateTime, DurationInMinutes Desc, id';
        
        system.debug('=====' + soql);
        
        return Database.query(soql);
    }
    
    // 検索用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;
    }
    
    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');
        
        pr.getParameters().put('mk', mdDay.addDays(-28).format());
        pr.getParameters().put('md', 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 getNextUrl() {
        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', mdDay.addDays(28).format());
        pr.getParameters().put('md', 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;
    }

    // {ユーザー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 WeekCalendarInfo {
        public String weekKey { 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 = OFSCalendarController.evtAccountMap.get(whatIdc);
                Campaign cpg = OFSCalendarController.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() {
            return maxTr == 0 ? 1 : maxTr;
        }

        public List<Map<String, String>> getMdKeyList3() {
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.weekKey);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.weekKey);

            List<Map<String, String>> rtn2 = new List<Map<String, String>>();
            
            Map<String, String> md2User = OFSCalendarController.mdKeyList2Map.get(this.weekKey)[0].clone();
            rtn2.add(md2User);
            
            for (Integer i = 1; i < OFSCalendarController.mdKeyList2Map.get(this.weekKey).size(); i++) {
                Map<String, String> md2 = OFSCalendarController.mdKeyList2Map.get(this.weekKey)[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 (OFSCalendarController.drMap.get(whatId) != null) {
                            Daily_Report__c dr = OFSCalendarController.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);
            }
            return rtn2;
        }
        
        // 週の行単位に変換、line は 1 から
        // maxTrが1以上の場合のみ呼び出す
        public List<List<Map<String, String>>> getRowInfoList() {
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.weekKey);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.weekKey);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.weekKey);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.weekKey);
            // Dailyの時だけ使う、重ね表示用
            List<Long> evtsStart = evtsStartMap.get(this.weekKey);
            List<Long> evtsEnd = evtsEndMap.get(this.weekKey);
            List<Integer> evtsZ = evtsZMap.get(this.weekKey);

            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 : OFSCalendarController.mdKeyListMap.get(this.weekKey)) {
                    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 (OFSCalendarController.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);
                            
                            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) + '%');
                            
                            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.weekKey);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.weekKey);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.weekKey);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.weekKey);
            // Dailyの時だけ使う、重ね表示用
            List<Long> evtsStart = evtsStartMap.get(this.weekKey);
            List<Long> evtsEnd = evtsEndMap.get(this.weekKey);
            List<Integer> evtsZ = evtsZMap.get(this.weekKey);

            List<List<Map<String, String>>> tdList = new List<List<Map<String, String>>>();
            Integer evtIdx = 0;
            for (Integer mdIdx = 0; mdIdx < OFSCalendarController.mdKeyListMap.get(this.weekKey).size(); mdIdx++) {
                String mdKey = OFSCalendarController.mdKeyListMap.get(this.weekKey)[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 (OFSCalendarController.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) / OFSCalendarController.mdKeyListMap.get(this.weekKey).size()) + '%');
                        ev.put('eWidth', ((e.DurationInMinutes / 0.6) / OFSCalendarController.mdKeyListMap.get(this.weekKey).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 及び 中身 を作る関数
        public WeekCalendarInfo(String weekKey) {
            this.weekKey = weekKey;

            OFSCalendarController.evtListsMapMap.put(this.weekKey, new Map<String, List<Event>>());
            OFSCalendarController.evtMarkedMapMap.put(this.weekKey, new Map<String, List<Integer>>());
            OFSCalendarController.searchWordsMapMap.put(this.weekKey, new Map<String, List<String>>());
            OFSCalendarController.whatIdsMapMap.put(this.weekKey, new Map<String, List<Id>>());
            // Dailyの時だけ使う、重ね表示用
            OFSCalendarController.evtsStartMap.put(this.weekKey, new List<Long>());
            OFSCalendarController.evtsEndMap.put(this.weekKey, new List<Long>());
            OFSCalendarController.evtsZMap.put(this.weekKey, new List<Integer>());
            
            Map<String, List<Event>> evtListsMap = evtListsMapMap.get(this.weekKey);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.weekKey);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.weekKey);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.weekKey);
            maxTr = 0;
            for (String mdKey : OFSCalendarController.mdKeyListMap.get(this.weekKey)) {
                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.weekKey);
            Map<String, List<Integer>> evtMarkedMap = evtMarkedMapMap.get(this.weekKey);
            Map<String, List<String>> searchWordsMap = searchWordsMapMap.get(this.weekKey);
            Map<String, List<Id>> whatIdsMap = whatIdsMapMap.get(this.weekKey);
            // Dailyの時だけ使う、重ね表示用
            List<Long> evtsStart = evtsStartMap.get(this.weekKey);
            List<Long> evtsEnd = evtsEndMap.get(this.weekKey);
            List<Integer> evtsZ = evtsZMap.get(this.weekKey);

System.debug('addEvent e.Id, searchText:' + e.Id + ',' + searchText);
            Datetime ead = e.StartDateTime;
            ead = DateTime.newInstance(e.ActivityDate.year(), e.ActivityDate.month(), e.ActivityDate.day());
            
            String mdKey = ead.format('H') + ':00';
            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 = OFSCalendarController.mvlCnMap.containsKey(mainVisit) ? OFSCalendarController.mvlCnMap.get(mainVisit) : mainVisit;
            e.Main_Visit_Location__c = mainVisit;
            String purposeType = e.Purpose_Type__c == null ? '' : e.Purpose_Type__c;
            purposeType = OFSCalendarController.purposeCnMap.containsKey(purposeType) ? OFSCalendarController.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 = OFSCalendarController.evtAccountMap.get(e.WhatId__c);
                Campaign cpg = OFSCalendarController.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 = OFSCalendarController.at2CnMap.containsKey(at2) ? OFSCalendarController.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) {
                OFSCalendarController.markCnt++;
                evtMarked.add(OFSCalendarController.markCnt);
            } else {
                evtMarked.add(0);
            }
System.debug('addEvent evtMarked.add:' + isMark);
            if (evtLists.size() > maxTr) {
                maxTr = evtLists.size();
            }
        }
    }
         @TestVisible
    public static void testI() {
        integer i = 0;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
    }
}