'use strict';

/**
 *
 *
 * @author Zhong
 * @date 2018/8/2
 * @version
 */

/*
* 清单导入模块,前端导入excel,进行数据提取，用lz-string进行压缩上传处理
* */

const importBills = (function(){
    //单元格数据是否存在
    function _isDef(data){
        return typeof data !== 'undefined' && data !== null && data !== '';
    }
    
    //去除转义字符
    function _deESC(data) {
        return _isDef(data) ? data.toString().replace(/[\r,\n,\s,\t]/g, '') : data;
    }

    function _deNR(data) {
        return _isDef(data) ? data.toString().replace(/\r\r/g, '\r') : data;
    }
    //find 返回最后匹配
    function findLast(datas, func) {
        let filter = datas.filter(func);
        if (filter.length > 0) {
            return filter[filter.length - 1];
        }
        return null;
    }
    const fileType = {
        gcl: 0, //工程量清单
        qdsl: 1 //清单示例
    };
    //获取列字段对应
    function getColMapping(type){
        if (type === 0) {   //工程量清单
            return {code: 0, name: 1, unit: 2, quantity: 4};
        } else {    //清单示例表
            return {code: 0, name: 1, unit: 2, quantity: 3};
        }
    }
    function isGCLHead(dataRow) {
        let cell = dataRow[0];
        return cell && cell.value === '工程量清单';
    }
    //分析文件，1、工程量清单 2、清单示例表
    function getFileType(sheetData) {
        let dataTable = sheetData.data.dataTable,
            rowCount = sheetData.rowCount;
        for (let row = 0; row < rowCount; row++) {
            if (isGCLHead(dataTable[row])) {
                return fileType.gcl;
            }
        }
        return fileType.qdsl;
    }
    //提取工程量清单数据
    //层级由depth确定，表格里最顶层depth为0（表头里一清单）,表格内容里数据的depth为空格数+1
    function extractGCLDatas(sheetData, colMapping) {
        //let colMapping = {code: 0, name: 1, unit: 2, quantity: 4};
        let dataTable = sheetData.data.dataTable,
            rowCount = sheetData.rowCount;
        let rst = [];
        for (let row = 0; row < rowCount; row++) {
            //表格中顶层节点
            if (isGCLHead(dataTable[row])) {
                let rootRow = dataTable[row + 2];
                let name = rootRow[0].value;
                let existsRoot = findLast(rst, x => x.name === name && x.depth === 0);
                if (!existsRoot) {
                    let root = {
                        ID: uuid.v1(), 
                        NextSiblingID: -1, 
                        ParentID: -1, 
                        name: name, 
                        depth: 0, 
                        parent: null,
                        unitPriceAnalysis: 1
                    };
                    let preData = findLast(rst, x => x.depth === root.depth);
                    if (preData) {
                        preData.NextSiblingID = root.ID;
                    }
                    rst.push(root);
                }
                row += 3;
                continue;
            }
            let code = dataTable[row][colMapping.code] ? dataTable[row][colMapping.code].value : null,
                name = dataTable[row][colMapping.name] ? dataTable[row][colMapping.name].value : null,
                unit = dataTable[row][colMapping.unit] ? dataTable[row][colMapping.unit].value : null,
                quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null;
            if (!code && !name || /合计/.test(code)) {   //过滤掉同时没有编号和名称的、过滤合计行
                continue;
            }
            //表格内的数据
            code = String(code);
            let depth = getDepth(code);
            let data = {
                ID: uuid.v1(), 
                NextSiblingID: -1, 
                ParentID: -1, 
                code: code, 
                name: name, 
                unit: unit, 
                quantity: quantity, 
                depth: depth,
                unitPriceAnalysis: 1,
            };
            let lastData = rst[rst.length - 1];
            //获取data的父节点链,成为兄弟节点，只能在父链里找前兄弟（不能跨父链）
            let parents = getParents(lastData);
            let preData = findLast(parents, x => x.depth === depth);
            if (preData) {
                preData.NextSiblingID = data.ID;
                data.ParentID = preData.ParentID;
                data.parent = preData.parent;
            } else {
                data.ParentID = lastData.ID;
                data.parent = lastData;
            }
            rst.push(data);

        }
        console.log(rst);
        return rst;
        function getDepth(code) {
            if (!code) {
                return 1;
            }
            let match = code.match(/\s/g);
            return match ? match.length + 1 : 1;
        }
    }

    function getParents(data) {
        let rst = [];
        let parent = data.parent;
        while (parent) {
            rst.push(parent);
            parent = parent.parent;
        }
        rst.push(data);
        return rst;
    }

    //获取编号前缀： 101-1 => 101   101-1-1 => 101-1
    function getPrefix(v) {
        if (!v) {
            return null;
        }
        let reg = /(.*)-/;
        let match = reg.exec(v);
        return match ? match[1] : null;
    }

    //提取清单示例数据
    function extractSLDatas(sheetData) {
        let colMapping = {code: 0, name: 1, unit: 2, quantity: 3};
        let dataTable = sheetData.data.dataTable,
            rowCount = sheetData.rowCount;
        let rst = [];
        let curRoot = null;
        for (let row = 0; row < rowCount; row++) {
            let code = dataTable[row][colMapping.code] && dataTable[row][colMapping.code].value ? String(dataTable[row][colMapping.code].value).trim() : null,
                name = dataTable[row][colMapping.name] ? dataTable[row][colMapping.name].value : null,
                unit = dataTable[row][colMapping.unit] ? dataTable[row][colMapping.unit].value : null,
                quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null;
            if (!code) {    //没有编号的数据，名称必须为:清单 第xx章，认为新的表根节点
                if (name && /清单 第\d+章/.test(name)) {
                    curRoot = {
                        code: null, 
                        name: name, 
                        ID: uuid.v1(), 
                        ParentID: -1, 
                        NextSiblingID: -1, 
                        parent: null,
                        unitPriceAnalysis: 1
                    };
                    rst.push(curRoot);
                } else {
                    curRoot = null;
                }
            } else if (!curRoot) {  //根节点为无效根节点，其下子数据全部过滤掉
                continue;
            } else {
                //有code且有有效表根节点
                let prefix = getPrefix(code);
                let data = {
                    code: code,
                    name: name,
                    unit: unit,
                    quantity: quantity,
                    ID: uuid.v1(),
                    NextSiblingID: -1,
                    unitPriceAnalysis: 1
                };
                let lastData = rst[rst.length - 1];
                let parents = getParents(lastData);
                //某数据编号为此数据的前缀，则某数据为此数据的父节点
                let parentData = findLast(parents, x => prefix === x.code);
                if (!parentData && prefix === '') { // -x的数据，在父链上找不到编号与prefix相同的数据时，父链上-x的数据，则这两数据为兄弟节点，没有则上一行数据为其父节点
                    let samePrefixData = findLast(parents, x => getPrefix(x.code) === prefix);
                    parentData = samePrefixData ? samePrefixData.parent : lastData;
                } else if (!parentData && prefix !== '') {  //不是-x的数据，在父链上找不到编号与prefix相同的数据时，表根节点为其父节点
                    parentData = curRoot;
                }
                data.ParentID = parentData.ID;
                data.parent = parentData;
                let preData = findLast(parents, x => x.ParentID === data.ParentID);
                if (preData) {
                    preData.NextSiblingID = data.ID;
                }
                rst.push(data);
            }
        }
        console.log(rst);
        return rst;
    }
    
    function extactDatas(sheets) {
        let rst = [];
        let curSheetType = null;
        for (let sheetName in sheets) {
            let sheetData = sheets[sheetName];
            let sheetType = getFileType(sheetData);
            if (curSheetType !== null && sheetType !== curSheetType) {
                throw 'excel文件中存在不同格式的表格。';
            }
            curSheetType = sheetType;
            let colMapping = getColMapping(sheetType);
            let datas = sheetType === fileType.gcl ? extractGCLDatas(sheetData, colMapping) : extractSLDatas(sheetData, colMapping);
            rst = rst.concat(datas);
        }
        //编号去除空格 清除多余数据 设置数据
        for (let data of rst) {
            if (data.code && typeof data.code === 'string') {
                data.code = data.code.replace(/\s/g, '');
            }
            if (data.unit === '㎡') {
                data.unit = 'm2';
            } else if (data.unit === 'm³') {
                data.unit = 'm3';
            }
            data.projectID = projectObj.project.ID();
            data.type = billType.BILL;
            delete data.parent;
            delete data.depth;
        }
        //将表根节点的ParentID设置成第100章至700章清单的ID
        let fixedBill = projectObj.project.Bills.tree.roots.find(node => node.data &&
            node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.ONE_SEVEN_BILLS);
        let rootDatas = rst.filter(data => data.ParentID === -1);
        for (let root of rootDatas) {
            root.ParentID = fixedBill.data.ID;
        }
        //清单 第100章 总则清单需要加上固定ID
        let oneHundredBills = rootDatas.find(data => data.name && /第100章/.test(data.name));
        if (oneHundredBills) {
            oneHundredBills.flags = [{flag: fixedFlag.ONE_HUNDRED_BILLS, fieldName: 'fixed'}];
        }
        return rst;
    }

    return {extactDatas}
})();