const log4js = require('log4js');
const {program} = require('commander');
const xlsx = require('node-xlsx');
const fs = require('fs');


const logger = log4js.getLogger("cgfx");

program
    .version('1.0.0')
    .description('An application for create geojson from xlsx.')
    .option('-l, --log-level <string>', 'log level [all < trace < debug < info < warn < error < fatal < mark < off]', 'debug')
    .option('-f, --from-file <string>', 'input xlsx file', 'grid/resut.xlsx')
    .option('-t, --to-file <string>', 'output geojson file', 'grid/grid.geojson')
    .option('-b, --bbox-fields <string>', 'bbox fields:minx,miny,maxx,maxy', 'grid_lon_min,grid_lat_min,grid_lon_max,grid_lat_max')
    .option('-i, --info-fields <string>', 'info fields:info1,info2', 'grid_addr,grid_fk_target,grid_fk,grid_ph,grid_acti,grid_label1,grid_label2,grid_label3,grid_label4')
    .option('-p, --prefix-field <string>', 'field prefix', 'app_app_cbam_lbs_grid_cust_label_d_f_v1.')

program.parse(process.argv)

const args = program.opts()

logger.level = args.logLevel;
logger.info(`args = ${JSON.stringify(args)}`)

function get_field_index(headers, args) {
    const fm = {}
    headers.forEach((v, i) => fm[v] = i)

    const res = {}

    const bboxFields = args.bboxFields.split(",")
    res.bboxIndex = bboxFields.map((v, i) => fm[args.prefixField + bboxFields[i]])

    const infoFields = args.infoFields.split(",")
    res.infoFields = infoFields
    res.infoIndex = infoFields.map((v, i) => fm[args.prefixField + infoFields[i]])

    return res;
}

function write_to_geojson_file(sheet, index_info, writer) {
    writer.write('{\n' +
        '"type": "FeatureCollection",\n' +
        '"name": "grid",\n' +
        '"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },\n' +
        '"features": [\n');
    let count = 0;
    let total = sheet.data.length;
    for (let i = 1; i < total; i++) {
        const row = sheet.data[i];
        let bbox = index_info.bboxIndex.map((v) => {
            return +row[v];
        });
        let props = {};
        index_info.infoIndex.forEach((v, i) => {
            props[index_info.infoFields[i]] = row[index_info.infoIndex[i]];
        });

        props["id"] = count;
        let coors = [[bbox[0], bbox[1]], [bbox[2], bbox[1]], [bbox[2], bbox[3]], [bbox[0], bbox[3]], [bbox[0], bbox[1]]]
        let feature = {"type": "Feature", "properties": props, "geometry": {"type": "Polygon", "coordinates": [coors]}}

        writer.write((i == 1 ? '' : ',\n') + JSON.stringify(feature))
        count++;

        if (count % 1000 == 0) {
            logger.info(`${i}/${total} ${new Number(i * 100 / total).toFixed()}...`)
        }
    }
    writer.write('\n]\n' +
        '}\n');

    logger.info(`${total}/${total} 100%...`)
}

function geojson_from_xlsx(args) {
    logger.info('load xlsx file, file = ' + args.fromFile)
    const sheets = xlsx.parse(args.fromFile)
    logger.info('xlsx file loaded')

    const sheet = sheets[0]
    const index_info = get_field_index(sheet.data[0], args)

    logger.info('start write to geojson, file = ' + args.toFile)
    let writer = fs.createWriteStream(args.toFile)
    write_to_geojson_file(sheet, index_info, writer)
    writer.close()

    logger.info('end write to geojson')
}

const start_time = new Date().getTime();

logger.info('start create geojson from xlsx ...')
geojson_from_xlsx(args);
logger.info('end create geojson from xlsx, spent time = ' + (new Date().getTime() - start_time)/1000 + "s");
