public class SelectProduct2Extension {
    /*****************親オブジェクトID******************/
    public String productMaterialId { get; set; }
    public String productDocMiddleId { get; set; }
    public String productCICId { get; set; }
    
    /*****************検索用******************/
    public Product2 pro { get; set; }
    public String family { get; set; }
    public String category2 { get; set; }
    public String category3 { get; set; }
    public String category4 { get; set; }
    public String category5 { get; set; }
    public String assetModelNo { get; set; }
    public String multiStatus { get; set; }
    
    /*****************画面表示Bean******************/
    public List<Product2Info> productRecords { get; set; }
    public Integer productCount { get; set; }
    //public String proCntText = null;
    //public String getProCntText() {
    //    return (productCount > 0) ? '共有' + productCount + '件产品' : '';
    //}
    public String saveType { get; set; }
    
    /*****************ソートキー******************/
    public String sortKey { get; set; }
    public String preSortKey { get; set; }
    public Boolean sortOrderAsc { get; set; }
    public String[] sortOrder { get; set; }
    public String[] columus = new String[]{ 'Asset_Model_No__c', 'MDM_Name__c', 'OT_CODE_no_link__c', 'Family', 'SFDA_Status__c',
                                            'Category2__c', 'Category3__c', 'Category4__c', 'Category5__c' };
    
    private List<Product2> productSelected = new List<Product2>();
    private List<String> productIds = new List<String>();
    private Map<String, String> selectedIdMap = new Map<String, String>();
    
    /*****************ソート時再検索条件（画面からの入力条件を無視するため）******************/
    private String nameForSort = null;
    private String cate1ForSort = null;
    private String cate2ForSort = null;
    private String cate3ForSort = null;
    private String cate4ForSort = null;
    private String cate5ForSort = null;
    private String statusForSort = null;
    
    private Integer productSelectLimitDisplay = Integer.valueOf(Label.Product_Select_Limit) - 1;
    
    public SelectProduct2Extension() {
        productRecords = new List<Product2Info>();
        
        productMaterialId = ApexPages.currentPage().getParameters().get('pmid');
        productDocMiddleId = ApexPages.currentPage().getParameters().get('pdmid');
        productCICId = ApexPages.currentPage().getParameters().get('cicid');
        
        pro = [select Id, Family from Product2 limit 1];
        
        // TODO Describeで対応？
        //Schema.DescribeFieldResult f = Product2.Family.getDescribe();
    }
    
    public void init() {
        // 選択済みの資料対象製品を取得
        this.makeProductIds();
        
        // 選択済みの製品を取得
        productSelected = [select Id, Name, MDM_Name__c, OT_CODE_no_link__c, Family, SFDA_Status__c, Asset_Model_No__c,
                           Intra_Trade_List_RMB__c, Foreign_Trade_List_US__c, Category2__c, Category3__c, Category4__c, Category5__c
                           from Product2 where Id in :productIds order by Asset_Model_No__c];
        for (Integer i = 0; i < productSelected.size(); i++) {
            // 501を超えた場合前500のみを出す
            if (i == productSelectLimitDisplay) continue;
            
            productRecords.add(new Product2Info(productSelected[i]));
            productRecords[i].check = true;
            productRecords[i].oldCheck = true;
            selectedIdMap.put(productSelected[i].Id, productSelected[i].Id);
        }
        
        productCount = productRecords.size();
        if (productCount > productSelectLimitDisplay) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '数据超过' + productSelectLimitDisplay + '件，只显示前' + productSelectLimitDisplay + '件'));
        } else {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '共有' + productCount + '件产品'));
        }
        //this.sortKey = '0';
        //this.preSortKey = '0';
        //this.sortOrderAsc = true;
        //this.sortOrder = new String[9];
        //this.sortOrder = new String[]{ '↑', '　', '　', '　', '　', '　', '　', '　', '　', '　' };
    }
    
    public void searchProduct() {
        if (String.isBlank(family) && String.isBlank(category2)
                && String.isBlank(category3) && String.isBlank(category4)
                    && String.isBlank(category5) && String.isBlank(assetModelNo)
                        && String.isBlank(multiStatus)) {
            return;
        }
        
        productRecords = new List<Product2Info>();
        
        String soql = this.makeSoql(family, category2, category3, category4, category5, assetModelNo, multiStatus);
        soql += ' order by Asset_Model_No__c limit ' + Label.Product_Select_Limit;
        List<Product2> queryList = Database.query(soql);
        
        // 選択済みの製品を取得
        productIds = new List<String>();
        this.makeProductIds();
        //ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, 'productIds::' + productIds.size() + '件产品'));
        selectedIdMap = new Map<String, String>();
        productSelected = [select Id, Name, MDM_Name__c, OT_CODE_no_link__c, Family, SFDA_Status__c, Asset_Model_No__c,
                           Intra_Trade_List_RMB__c, Foreign_Trade_List_US__c, Category2__c, Category3__c, Category4__c, Category5__c
                           from Product2 where Id in :productIds order by Asset_Model_No__c];
        for (Integer i = 0; i < productSelected.size(); i++) {
            selectedIdMap.put(productSelected[i].Id, productSelected[i].Id);
        }
        
        // 選択済みのものにチェックを付ける
        for (Integer i = 0; i < queryList.size(); i++) {
            // 501を超えた場合前500のみを出す
            if (i == productSelectLimitDisplay) continue;
            
            productRecords.add(new Product2Info(queryList[i]));
            if (selectedIdMap.containsKey(queryList[i].Id)) {
                productRecords[i].check = true;
                productRecords[i].oldCheck = true;
            }
        }
        
        this.sortKey = '0';
        this.preSortKey = '0';
        this.sortOrderAsc = true;
        this.sortOrder = new String[8];
        this.sortOrder = new String[]{ '↑', '　', '　', '　', '　', '　', '　', '　', '　'};
        
        cate1ForSort = family;
        cate2ForSort = category2;
        cate3ForSort = category3;
        cate4ForSort = category4;
        cate5ForSort = category5;
        nameForSort = assetModelNo;
        statusForSort = multiStatus;
        
        productCount = productRecords.size();
        if (productCount > productSelectLimitDisplay) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '数据超过' + productSelectLimitDisplay + '件，只显示前' + productSelectLimitDisplay + '件'));
        } else {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '共有' + productCount + '件产品'));
        }
    }
    
    public void sortTable() {
        if (String.isBlank(cate1ForSort) && String.isBlank(cate2ForSort)
                && String.isBlank(cate3ForSort) && String.isBlank(cate4ForSort)
                    && String.isBlank(cate5ForSort) && String.isBlank(nameForSort)
                        && String.isBlank(statusForSort)) {
            return;
        }
        
        productRecords = new List<Product2Info>();
        
        if (this.sortKey == this.preSortKey) {
            // 方向が変わるのみ
            this.sortOrderAsc = !this.sortOrderAsc;
            this.sortOrder[Integer.valueOf(this.sortKey)] = (this.sortOrderAsc == true ? '↑' : '↓');
        } else {
            this.sortOrderAsc = true;
            this.sortOrder[Integer.valueOf(this.preSortKey)] = '　';
            this.sortOrder[Integer.valueOf(this.sortKey)] = (this.sortOrderAsc == true ? '↑' : '↓');
        }
        this.preSortKey = this.sortKey;
        
        String soql = this.makeSoql(cate1ForSort, cate2ForSort, cate3ForSort, cate4ForSort, cate5ForSort, nameForSort, statusForSort);
        soql += ' order by ' + this.columus[Integer.valueOf(this.sortKey)] + ' ' + (this.sortOrderAsc == true ? 'asc nulls first' : 'desc nulls last') + ' limit ' + Label.Product_Select_Limit;
        List<Product2> queryList = Database.query(soql);

        // 選択済みの製品を取得
        this.makeProductIds();
        
        selectedIdMap = new Map<String, String>();
        productSelected = [select Id, Name, MDM_Name__c, OT_CODE_no_link__c, Family, SFDA_Status__c, Asset_Model_No__c,
                           Intra_Trade_List_RMB__c, Foreign_Trade_List_US__c, Category2__c, Category3__c, Category4__c, Category5__c
                           from Product2 where Id in :productIds order by Asset_Model_No__c];
        for (Integer i = 0; i < productSelected.size(); i++) {
            selectedIdMap.put(productSelected[i].Id, productSelected[i].Id);
        }
        
        // 選択済みのものにチェックを付ける
        for (Integer i = 0; i < queryList.size(); i++) {
            // 501を超えた場合前500のみを出す
            if (i == productSelectLimitDisplay) continue;
            
            productRecords.add(new Product2Info(queryList[i]));
            if (selectedIdMap.containsKey(queryList[i].Id)) {
                productRecords[i].check = true;
                productRecords[i].oldCheck = true;
            }
        }
        
        productCount = productRecords.size();
        if (productCount > productSelectLimitDisplay) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '数据超过' + productSelectLimitDisplay + '件，只显示前' + productSelectLimitDisplay + '件'));
        } else {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '共有' + productCount + '件产品'));
        }
    }
    
    public PageReference save() {
        
        List<String> mfProIds = new List<String>();
        List<Material_For__c> mfIns = new List<Material_For__c>();
        List<Material_For__c> mfDel = new List<Material_For__c>();
        
        List<String> pdmtProIds = new List<String>();
        List<Product_and_document_middle_table__c> pdmtIns = new List<Product_and_document_middle_table__c>();
        List<Product_and_document_middle_table__c> pdmtDel = new List<Product_and_document_middle_table__c>();
        
        List<String> cpmtProIds = new List<String>();
        List<CIC_case_and_product_middle_table__c> cpmtIns = new List<CIC_case_and_product_middle_table__c>();
        List<CIC_case_and_product_middle_table__c> cpmtDel = new List<CIC_case_and_product_middle_table__c>();
        
        Savepoint sp = Database.setSavepoint();
        try {
            for (Product2Info prInfo : productRecords) {
                // 画面上にチェックした、且つ未登録の製品
                if (prInfo.check && !selectedIdMap.containsKey(prInfo.rec.Id)) {
                    // SFDA証書から
                    if (!String.isBlank(productMaterialId)) {
                        Material_For__c mf = new Material_For__c(
                            Material__c = productMaterialId,
                            Product__c = prInfo.rec.Id
                        );
                        mfIns.add(mf);
                    // 製品資料から
                    } else if (!String.isBlank(productDocMiddleId)) {
                        Product_and_document_middle_table__c pdmt = new Product_and_document_middle_table__c(
                            Product_document__c = productDocMiddleId,
                            Product_name__c = prInfo.rec.Id
                        );
                        pdmtIns.add(pdmt);
                    // CICから
                    } else if (!String.isBlank(productCICId)) {
                        CIC_case_and_product_middle_table__c cmpt = new CIC_case_and_product_middle_table__c(
                            CIC__c = productCICId,
                            Product__c = prInfo.rec.Id
                        );
                        cpmtIns.add(cmpt);
                    } else {}
                }
                // 画面上にチェックなし、且つ以前がチェックされた製品
                if (!prInfo.check && prInfo.oldCheck) {
                    // SFDA証書から
                    if (!String.isBlank(productMaterialId)) {
                        mfProIds.add(prInfo.rec.Id);
                    // 製品資料から
                    } else if (!String.isBlank(productDocMiddleId)) {
                        pdmtProIds.add(prInfo.rec.Id);
                    // CICから
                    } else if (!String.isBlank(productCICId)) {
                        cpmtProIds.add(prInfo.rec.Id);
                    } else {}
                }
            }
            
            // 削除
            if (mfProIds.size() > 0) ControllerUtil.delMaterialFor(productMaterialId, mfProIds);
            if (pdmtProIds.size() > 0) ControllerUtil.delProDocMidTbl(productDocMiddleId, pdmtProIds);
            if (cpmtProIds.size() > 0) ControllerUtil.delCicProMidTbl(productCICId, cpmtProIds);
            
            // 新規
            ControllerUtil.insMaterialFor(mfIns);
            ControllerUtil.insProDocMidTbl(pdmtIns);
            ControllerUtil.insCicProMidTbl(cpmtIns);
        } catch (Exception ex) {
            ApexPages.addMessages(ex);
            Database.rollback(sp);
            return null;
        }
        
        if (saveType == '1') {
            searchProduct();
            saveType = '';
            return null;
        } else if (saveType == '2') {
            sortTable();
            saveType = '';
            return null;
        } else {
            return cancel();
        }
    }
    
    public PageReference cancel() {
System.debug('cancel start productCICId=' + this.productCICId);
        PageReference ret = null;
        if (!String.isBlank(this.productMaterialId)) {
            ret = new PageReference('/' + this.productMaterialId);
        }
        if (!String.isBlank(this.productDocMiddleId)) {
            ret = new PageReference('/' + this.productDocMiddleId);
        }
        if (!String.isBlank(this.productCICId)) {
            ret = new PageReference('/' + this.productCICId);
        }
        return ret;
    }
    
    private String makeSoql(String cate1, String cate2, String cate3, String cate4,
            String cate5, String assMode, String status) {
        
        String soql = 'select Id, Name, MDM_Name__c, OT_CODE_no_link__c, Family, SFDA_Status__c, Asset_Model_No__c,'
                    + ' Intra_Trade_List_RMB__c, Foreign_Trade_List_US__c, Category2__c, Category3__c, Category4__c, Category5__c'
                    + ' from Product2 where IsActive = true';
        // 製品資料とCICの場合、SFDA状態を見る
        if (!String.isBlank(productDocMiddleId) || !String.isBlank(productCICId)) {
            soql += ' and SFDA_Status__c <> \'準備中\' and SFDA_Status__c <> \'新製品申請中\'';
        }
        // Familyはプルダウン
        if (!String.isBlank(cate1)) {
            soql += ' and Family = \'' + cate1 + '\'';
        }
        if (!String.isBlank(cate2)) {
            soql += ' and Category2__c like \'%' + cate2 + '%\'';
        }
        if (!String.isBlank(cate3)) {
            soql += ' and Category3__c like \'%' + cate3 + '%\'';
        }
        if (!String.isBlank(cate4)) {
            soql += ' and Category4__c like \'%' + cate4 + '%\'';
        }
        if (!String.isBlank(cate5)) {
            soql += ' and Category5__c like \'%' + cate5 + '%\'';
        }
        if (!String.isBlank(assMode)) {
            soql += ' and Asset_Model_No__c like \'%' + assMode + '%\'';
        }
        if (!String.isBlank(status)) {
            soql += ' and (';
            List<String> vals = status.split('_', -1);
            for (Integer i = 0; i < vals.size(); i++) {
                if (i == vals.size() - 1) {
                    soql += ' SFDA_Status__c = \'' + vals[i] + '\')';
                } else {
                    soql += ' SFDA_Status__c = \'' + vals[i] + '\' or';
                }
            }
        }
        
        return soql;
    }
    
    private void makeProductIds() {
        productIds = new List<String>();
        if (!String.isBlank(productMaterialId)) {
            List<Material_For__c> mfList = [select Product__c from Material_For__c where Material__c = :productMaterialId];
            for (Material_For__c mf : mfList) {
                productIds.add(mf.Product__c);
            }
        }
        if (!String.isBlank(productDocMiddleId)) {
            List<Product_and_document_middle_table__c> pdmtList = [select Product_name__c from Product_and_document_middle_table__c where Product_document__c = :productDocMiddleId];
            for (Product_and_document_middle_table__c pdmt : pdmtList) {
                productIds.add(pdmt.Product_name__c);
            }
        }
        if (!String.isBlank(productCICId)) {
            List<CIC_case_and_product_middle_table__c> cpmtList = [select Product__c from CIC_case_and_product_middle_table__c where CIC__c = :productCICId];
            for (CIC_case_and_product_middle_table__c cpmt : cpmtList) {
                productIds.add(cpmt.Product__c);
            }
        }
    }
    
    class Product2Info {
        public Product2 rec { get; set; }
        public Boolean check { get; set; }
        public Boolean oldCheck { get; set; }
        
        public Product2Info(Product2 record) {
            rec = record;
            check = false;
            oldCheck = false;
        }
    }
}