const xlsx = require('node-xlsx');
const path = require('path');

/**
 *   onceSheetBecomeOfblockData 将excel文件的指定sheet解析成数据块数据
 * @param fileName 文件名称
 * @param sheetName 表名称
 * @returns [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
 */
export function onceSheetBecomeOfblockData(fileName, sheetName) {
    let {sheetMap} = getExcel( path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", fileName ));
    let thisBlockData = getBlockData(sheetMap[sheetName]);
    return thisBlockData;
}

/**
 * excelBecomeOfBlockData 将excel所有的sheet解析成数据块
 * @param fileName 文件名称
 * @returns {"sheetName1":[ {blockData:数据块(二维数组), blockTitle:"数据标题"}], ...}
 */
export function excelBecomeOfBlockData(fileName) {
    let {sheetMap} = getExcel( path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", fileName ));
    let result = {};
    for (let sheetName in sheetMap) {
        result[sheetName] = getBlockData(sheetMap[sheetName]);
    }
    return result;
}

/**
 *  planaryArrayBecomeOfBlockData  将符合excel规则的sheet二维数组转为 数据块
 * @param dataList excel解出来的数据
 * @returns thisBlockData 返回数据块集合 格式：blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
 */
export function planaryArrayBecomeOfBlockData(planaryArray) {
    return getBlockData(planaryArray);;
}


//===

/**
 * getBlockData 数据分块 
 * @param dataList  解析出来的excel二维数组
 * @returns 返回数据块集合 格式：blockList = [ {blockData:数据块(二维数组), blockTitle:"数据标题"}]
 */
function getBlockData(dataList) {
    let blockList = [];
    for (let i = 0; i < 999; i++) {
        let {blockData, blockTitle, notItem, delDataList} = checkBlock(dataList);
        if (notItem) break;
        dataList = delDataList;
        if (blockTitle) blockList.push({blockData, blockTitle});
    }
    return blockList;
}

function getListFristNotNullItemIndex(list) { //获取起始坐标
    if (!list.length) return null;
    for (let i = 0; i < list.length; i++) {
        if (list[i]) return i;
    }
}


function getListFirstNullItemIndex(startX, list) { //获取第一个为空的坐标
    if (!list.length) return null;
    let checkItem = false;
    let firstItemIndex = 0;
    for (let i = startX; i <= list.length; i++) {
        let item = list[i];
        if (!checkItem && item) checkItem = true;
        
        if (checkItem && !item) {
            firstItemIndex = i;
            break;
        }
    }
    return firstItemIndex;
}
function listRegionIsNull(list, startX, endX) { //指定区间内数据是否未空
    let isNull = true;
    if ( !list.length ) return isNull;

    for (let i = startX; i < endX; i++) {
        let item = list[i];
        if (item) {
            isNull = false;
            break;
        }
    }
    return isNull;
}

function thisListNotItem(list) {
    for (let i = 0; i < list.length; i++) {
        if (list[i]) return false;
    }
    return true
}

function checkBlock(dataList) {
    //纵向有效起始点
    let startY = 0;
    let startX = 0;
    let isNotBlockTitle = false; //没有块标题
    let isLook = false;
    let endX = 0;//x轴最长结束下标 【包括下标】
    

    let blockTitle = ''; //标题块名称

    let notItem = true;

    for (let i = 0; i < dataList.length; i++) {
        let childList = dataList[i] || [];

        if (!thisListNotItem(childList)) {
            
            if ( !isLook ) {
                let thisRoowStartX = getListFristNotNullItemIndex(childList);
                let thisRoowLastItem = childList[thisRoowStartX + 1];
                let LastList = dataList[i+1] || [];
                // let lastRoowStartX = getListFristNotNullItemIndex(LastList);
                let lastRoowHaveItem = LastList[thisRoowStartX];
                if ( thisRoowLastItem || (LastList.length && lastRoowHaveItem)  ) {
                    
                    if (lastRoowHaveItem && thisRoowLastItem ) {
                        isNotBlockTitle = true; //不存在标题块
                        blockTitle = `${thisRoowStartX}_${i}`;
                        startY = i;
                        startX = thisRoowStartX;
                    }
                    else {
                        blockTitle = dataList[i][thisRoowStartX];
                        dataList[i][thisRoowStartX] = null;

                        if ( thisRoowLastItem ) { // 同行存在元素 标题在y轴上
                            startY = i;
                            startX = thisRoowStartX + 1;
                        } else {  // 同行存在元素 标题在x轴上
                            startY = i + 1;
                            startX = thisRoowStartX;
                        }
                    }
                    
                    isLook = true;
                } else { //只有标题 无内容
                    console.log(dataList[i][thisRoowStartX]);
                    dataList[i][thisRoowStartX] = null;
                }
                
            } else {
                //测量最大连续长度
                let firstNullX = getListFirstNullItemIndex(startX, childList);
                if (firstNullX) endX = Math.max(endX, firstNullX-1);
                break;
            }
            notItem = false;
        }
    }
    let endY = 0;//y轴连续下标 【包括下标】

    let yInfoStart = false;
    let yInfoEnd = false;

    for (let y = startY; y < dataList.length; y++) {
        //纵向找连续性
        let thisRoow = dataList[y];
        let regionIsNull = listRegionIsNull(thisRoow, startX, endX);
        if (!regionIsNull) {
            endY = y;
            if (!yInfoStart) yInfoStart = true;
        }
        if (yInfoStart && regionIsNull) yInfoEnd = true;
        if (yInfoEnd) break;
    }
    
    let blockData = [];
    for (let y = startY; y <= endY; y++) {
        let onceList = [];
        for (let x = startX; x <= endX; x++) {
            onceList.push(dataList[y][x]);
            dataList[y][x] = null;
        }
        blockData.push(onceList);
    }

    return {blockData, blockTitle, delDataList:dataList,notItem};
}



//获取单个excel文件的数据
function getExcel(filePath) {
    const workSheetsFromFile = xlsx.parse(filePath);
    let sheetMap = {};
    let sheetList = [];

    for (let i = 0; i < workSheetsFromFile.length; i++) {
        let sheetInfo = workSheetsFromFile[i];
        sheetMap[sheetInfo.name] = sheetInfo.data;
        sheetList.push(sheetInfo);
    }

    return {sheetMap, sheetList}  
}