//#import app.js
//#import $owl_apps:services/modelService.jsx
//#import $owl_app_sections:services/modelService.jsx
//#import $owl_app_fields:services/modelService.jsx
//#import Util.js

function parseFieldType(fieldType) {
    if (fieldType.indexOf('string') >= 0 || fieldType.indexOf('number') >= 0) {
        var idx = fieldType.indexOf('(')
        var idx1 = fieldType.indexOf(')')
        var sNum = fieldType.substring(idx + 1, idx1)
        var fieldSize = parseInt(sNum)
        if (fieldType.indexOf('string') >= 0) {
            var t = 'string'
        }
        else {
            var t = 'number'
        }
        return {
            fieldType: t,
            fieldSize: fieldSize,
        }
    }
    else {
        return {
            fieldType: fieldType,
        }
    }
}


function parseFieldAttrs(fieldAttrs) {
    var attrs = fieldAttrs.split(',')
    var fieldType = attrs[0]
    var attrObj = parseFieldType(fieldType)
    for (var i = 1; i < attrs.length; i++) {
        var attr = attrs[i]
        var pair = attr.split(':')
        if (pair.length == 2) {
            attrObj[pair[0].trim()] = pair[1].trim()
        } else {
            attrObj[pair[0].trim()] = 'false'
        }
    }

    if (attrObj.fieldType == 'choice') {
        var values = attrObj.values
        var va = values.split('/')
        var options = va.map((v) => v.split('_'))
        attrObj.options = options
    }
    return attrObj
}

function parseSpec(specString) {
    var parts = specString.split(';')
    var fieldLabel = ''
    if (parts.length >= 2) {
        fieldLabel = parts[1]
        var specObj = parseFieldAttrs(parts[0])
        specObj['fieldLabel'] = fieldLabel

        /*if(specObj["defaultValue"]){
          let v = specObj["defaultValue"];
          v = getEnvValue(v);
          specObj.defaultValue = v;
        }*/
        return specObj
    }
    return null
}

function getFields(subForm,sectionKey,appId){
    if(!subForm){
        return [];
    }
    var fields = [];
    var meta = subForm["#meta"];
    if(!meta){
        meta = {};
    }
    var includeKey = meta.includeKey;
    if(!includeKey){
        includeKey = 'yes';
    }
    for(var key in subForm){

        if(key==='#meta'){
            continue;
        }
        if(key==='_t'){
            continue;
        }
        if(key===''){
            continue;
        }
        v = subForm[key];
        if(typeof v === 'object'){
            if(Array.isArray(v)){
                var subFields = getFields(v[0],key,appId);
                if(subFields){
                    subFields.forEach(function(f){
                        fields.push(f);
                    })
                }
            }
            else{
                var subFields = getFields(v,key,appId);
                if(subFields){
                    subFields.forEach(function(f){
                        fields.push(f);
                    })
                }
            }
        }
        else if(typeof v==='string'){
            var f = parseSpec(v);
            if(f){
                f.fieldKey = key;
                f.origKey = key;
                f.sectionKey = sectionKey;
                f.tableId = appId;
                f.includeKey = includeKey
                fields.push(f);
            }
            else{
            }

        }
    }
    return fields;

}

function getSections(specObj,appId) {

    var sections = [];

    for (var key in specObj) {
        if (key === '#meta') {
            continue;
        }
        var field = specObj[key];
        if (typeof field === 'string') {
            continue;
        } else if (Array.isArray(field)) {
            var meta = field[0]["#meta"]
            if (!meta) {
                continue;
            }
            var section = meta;
            section.sectionKey = key;
            section.isArray = 'true';
            section.tableId = appId;
            sections.push(section);
        } else if (typeof field === 'object') {
            var meta = field["#meta"];
            if (!meta) {
                continue;
            }
            var section = meta;
            section.sectionKey = key;
            section.isArray = 'false';
            section.tableId  = appId;
            sections.push(section);

        }
    }
    return sections;
}

function getOldSections(appId) {
    var searchArgs = {
        tableId: appId
    }

    var sr = owl_app_sectionsService.search("0", searchArgs, null, 0, 10000, null);
    if (sr.state === 'ok') {
        return sr.list;
    }
    return [];
}

function getOldFields(appId){
    var searchArgs = {
        tableId:appId
    }
    var sr = owl_app_fieldsService.search("0",searchArgs,null,0,10000,null);
    if(sr.state === 'ok'){
        return sr.list;
    }
    return [];

}


function addNewSections(added) {
    for (var i = 0; i < added.length; i++) {
        var s = added[i];
        owl_app_sectionsService.add(s);
    }
}

function addNewFields(added) {
    for (var i = 0; i < added.length; i++) {
        var f = added[i];
        owl_app_fieldsService.add(f);
        $.log("addNewFields,f=" + JSON.stringify(f));
    }
}

function removeDeletedSections(deleted) {
    for (var i = 0; i < deleted.length; i++) {
        var d = deleted[i];
        owl_app_sectionsService.del(d.id);
    }
}

function removeDeletedFields(deleted) {
    for (var i = 0; i < deleted.length; i++) {
        var d = deleted[i];
        owl_app_fieldsService.del(d.id);
    }
}

function updateSections(oldSections, sections) {
    for (var i = 0; i < oldSections.length; i++) {
        var o = oldSections[i];
        for (var j = 0; j < sections.length; j++) {
            var n = sections[j];
            if (n.sectionKey == o.sectionKey) {
                var oo = owl_app_sectionsService.get(o.id);
                Object.assign(oo, n);
                owl_app_sectionsService.update(oo);
            }
        }
    }
}
function isScalar(o){
    if(o===null){
        return false;
    }
    return typeof o === 'string';
}


function isEqual(r1,r2){
    var ignoreKeys = ['_type','_matched','_v',"owl_createTime","owl_modifyTime","_t","id","_m"];
    if(r1==null && r2==null){
        return true;
    }
    if(r1==null || r2==null){
        return false;
    }
    if(isScalar(r1) || isScalar(r2)){
        return r1===r2;
    }
    //now assert a1!=null && r2!=null
    var ks1 = Object.keys(r1);
    var ks2 = Object.keys(r2);

    ks1 = ks1.filter(function(k){
        return ignoreKeys.indexOf(k)===-1;
    });

    ks2 = ks2.filter(function(k){
        return ignoreKeys.indexOf(k)===-1;
    });

    if(ks1.length!==ks2.length){
        $.log("ks1.length!==ks2.length,ks1="+JSON.stringify(ks1)+",ks2="+JSON.stringify(ks2));
        return false;
    }
    for(var i=0; i<ks1.length; i++){
        var k = ks1[i];
        if(Array.isArray(r1[k])){
            if(r1[k].length!==r2[k].length){
                return false;
            }
            if(JSON.stringify(r1[k])!==JSON.stringify(r2[k])){
                $.log("r1!=r2,r1=" + JSON.stringify(r1[k]) + ",r2=" +JSON.stringify(r2[k]));
                return false;
            }

        }
        else{
            if(r1[k]!==r2[k]){
                $.log("r1!=r2,r1=" + JSON.stringify(r1[k]) + ",r2=" +JSON.stringify(r2[k]));
                return false;
            }
        }
    }
    return true;

}

function updateFields(oldFields, fields) {
    var ignoreKeys = ['_type','_matched','_v',"owl_createTime","owl_modifyTime","_t","id"];
    for (var i = 0; i < oldFields.length; i++) {
        var o = oldFields[i];
        for (var j = 0; j < fields.length; j++) {
            var n = fields[j];
            if (n.sectionKey === o.sectionKey && n.fieldKey === o.fieldKey) {
                var oo = owl_app_fieldsService.get(o.id);
                if(!isEqual(oo,n)){
                    $.log("update field......new=" + JSON.stringify(n) + ", old=" + JSON.stringify(oo)+",o=" + JSON.stringify(o));
                    Object.assign(oo, n);
                    for(var okey in oo){
                        if(ignoreKeys.indexOf(okey)===-1){
                            if(!n[okey]){
                                $.log("delete " + okey)
                                delete oo[okey];
                            }
                        }
                    }
                    // $.log("update:" + JSON.stringify(oo));
                    try{
                        owl_app_fieldsService.update(oo);
                    }
                    catch(e){
                        owl_app_fieldsService.del(o.id);
                        owl_app_fieldsService.add(oo);
                    }


                }

            }
        }
    }
}

function getDeletedSections(sections, oldSections) {
    //在老sections但是不再新sections里面的数据，就是被删除的
    var deleted = [];
    for (var i = 0; i < oldSections.length; i++) {
        var old = oldSections[i];
        var found = false;
        for (var j = 0; j < sections.length; j++) {
            var s = sections[j];
            if (s.sectionKey === old.sectionKey) {
                found = true;
            }
        }
        if (!found) {
            deleted.push(old);
        }
    }
    return deleted;
}

function getDeletedFields(fields, oldFields) {
    //在老sections但是不再新sections里面的数据，就是被删除的
    var deleted = [];
    for (var i = 0; i < oldFields.length; i++) {
        var old = oldFields[i];
        var found = false;
        for (var j = 0; j < fields.length; j++) {
            var f = fields[j];
            if (f.sectionKey ===f.sectionKey && f.fieldKey === old.fieldKey) {
                found = true;
            }
        }
        if (!found) {
            deleted.push(old);
        }
    }
    return deleted;
}

function getAddedSections(sections, oldSections) {
    var added = [];
    for (var i = 0; i < sections.length; i++) {
        var s = sections[i];
        var found = false;
        for (var j = 0; j < oldSections.length; j++) {
            var old = oldSections[j];
            if (s.sectionKey === old.sectionKey) {
                found = true;
            }
        }
        if (!found) {
            added.push(s);
        }
    }
    return added;
}


function getAddedFields(fields, oldFields) {
    var added = [];
    for (var i = 0; i < fields.length; i++) {
        var s = fields[i];
        var found = false;
        for (var j = 0; j < oldFields.length; j++) {
            var old = oldFields[j];
            if (s.sectionKey === old.sectionKey && s.fieldKey === old.fieldKey) {
                found = true;
            }
        }
        if (!found) {
            added.push(s);
        }
    }
    return added;
}

function main() {
    var allapps = AppService.getIndependentApps('head_merchant', 0, -1);
    // $.log("allapps,length=" + allapps.length);
    for (var i = 0; i < allapps.length; i++) {
        var app = allapps[i];
        var appId = app.id;
        var name = null;
        var isWidget = null;
        var isHide = null;
        var project = null;
        var group = null;
        var groupId = null;
        var groupName = null;
        var pos = null;
        // try {
        var meta = AppService.getAppMeta(app.id);
        if(meta){
            var subMeta = meta["#meta"];
            isWidget = meta.isWidget ? 'yes' : 'no';
            if (subMeta) {
                isHide = subMeta.hide == 'true' ? 'yes' : 'no';
                project = subMeta.project;
                group = subMeta.group;
                pos = subMeta.pos;
                name = subMeta.rem;

                // $.log("subMeta:" + JSON.stringify(subMeta));
            }
        }

        var app = {
            tableId: appId,
            name: name,
            isWidget: isWidget,
            isHide: isHide,
            project: project,
            pos: pos

        }

        if (group) {
            if (typeof group == 'string') {
                app.group = null;
                app.groupId = group;
                app.groupName = group;
            } else {
                app.group = null;
                app.groupId = group.id;
                app.groupName = group.name;
                app.groupPos = group.pos;
            }

        }
        var id = "owl_apps_" + appId;
        if(appId=='owl_mall_p'){
            $.log("app=" + JSON.stringify(app));
        }
        var owlapp = owl_appsService.get(id);
        if (owlapp) {
            owlapp.name = app.name;
            owlapp.isWidget = app.isWidget;
            owlapp.isHide = app.isHide;
            owlapp.tableId = appId;
            owlapp.project = app.project;
            owlapp.pos = app.pos;
            owlapp.groupId = app.groupId;
            owlapp.groupName = app.groupName;
            owlapp.groupPos = app.groupPos;
            owlapp.group = null;
            owlapp._orgId = '0';
            owlapp._orgIds = ['0'];
            if(appId=='owl_mall_p'){
                $.log("owlapp=" + JSON.stringify(owlapp));
            }
            owl_appsService.update(owlapp);
        } else {
            owl_appsService.add(app);
        }
        // } catch (e) {
        //     $.log("meta is not valid:" + app.id);
        //     return false;
        // }

        var spec = $.getAppProgram(appId, "spec.json");
        if(!spec){
            continue;
        }
        var specObj = JSON.parse(spec);


        var sections = getSections(specObj,appId);


        //找到需要删除的
        var oldSections = getOldSections(appId);
        var deleted = getDeletedSections(sections, oldSections);
        var added = getAddedSections(sections, oldSections);

        // $.log("appId=" + appId + ",sections.length=" + sections.length + ", added.length=" + added.length + ",deleted.length=" + deleted.length);
        // $.log("appId=" + appId + ",oldSections.length=" + oldSections.length);

        removeDeletedSections(deleted);

        //添加
        addNewSections(added);


        // 更新
        updateSections(oldSections, sections);


        var fields = getFields(specObj,'main',appId);
        var oldFields = getOldFields(appId);
        var deletedFields = getDeletedFields(fields,oldFields);
        var addedFields = getAddedFields(fields,oldFields);
        removeDeletedFields(deletedFields);
        addNewFields(addedFields);
        updateFields(oldFields,fields);


    }
    // $.log("refresh_apps_jobs ended.");

}

main();