//#import app.js
//#import $owl_apps:services/modelService.jsx
//#import $owl_app_sections:services/modelService.jsx
//#import $owl_app_fields:services/modelService.jsx
//#import $owl_app_plugins: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;
    $.log("meta.includeKey=" + includeKey + ",sectionKey=" + sectionKey);
    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 getPlugins(specObj, tableId, tableName) {
    var meta = specObj["#meta"];
    if (!meta) {
        return [];
    }

    var plugins = meta.formPlugins;
    if (!plugins) {
        return [];
    }
    return plugins.map(function (plugin) {
        return {
            tableId: tableId,
            tableName: tableName,
            label: plugin.label,
            action: plugin.action,
            pluginId: plugin.id || plugin.action,
            position: plugin.position,
            help: plugin.help
        }
    });
}

function getOldPlugins(appId) {
    var searchArgs = {
        tableId: appId
    }
    var sr = owl_app_pluginsService.search(null, searchArgs, null, 0, 10000, null);
    if (sr.state === 'ok') {
        return sr.list;
    }
    return [];

}

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(null, 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];
        if(s){
            owl_app_sectionsService.add(s);
        }

    }
}

function addNewFields(added) {
    for (var i = 0; i < added.length; i++) {
        var f = added[i];
        if(f){
            owl_app_fieldsService.add(f);
        }

    }
}

function removeDeletedSections(deleted) {
    for (var i = 0; i < deleted.length; i++) {
        var d = deleted[i];
        if(d){
            owl_app_sectionsService.del(d.id);
        }

    }
}

function removeDeletedFields(deleted) {
    for (var i = 0; i < deleted.length; i++) {
        var d = deleted[i];
        if(d){
            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])) {
            0.
            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 getDeletedPlugins(plugins, oldPlugins) {
    var deleted = [];
    for (var i = 0; i < oldPlugins.length; i++) {
        var old = oldPlugins[i];
        var found = false;
        for (var j = 0; j < plugins.length; j++) {
            var s = plugins[j];
            if (s.label === old.label &&
                s.action === old.action &&
                s.pluginId === old.pluginId &&
                s.position === old.position &&
                s.tableId === old.tableId &&
                s.tableName === old.tableName &&
                s.help === old.help) {
                found = true;
            }

        }
        if (!found) {
            deleted.push(old);
        }
    }
    return deleted;
}

function getNewPlugins(plugins, oldPlugins) {
    var newPlugins = [];
    for (var i = 0; i < plugins.length; i++) {
        var plugin = plugins[i];
        var found = false;
        for (var j = 0; j < oldPlugins.length; j++) {
            var old = oldPlugins[j];
            if (plugin.label === old.label &&
                plugin.action === old.action &&
                plugin.pluginId === old.pluginId &&
                plugin.position === old.position &&
                plugin.tableId === old.tableId &&
                plugin.tableName === old.tableName &&
                plugin.help === old.help) {
                found = true;
            }

        }
        if (!found) {
            newPlugins.push(plugin);
        }
    }
    return newPlugins;
}

function removeDeletedPlugins(deleted) {
    if (!deleted) {
        return;
    }
    for (var i = 0; i < deleted.length; i++) {
        var d = deleted[i];
        owl_app_pluginsService.del(d.id);
    }
}

function addNewPlugins(newPlugins) {
    if (!newPlugins) {
        return;
    }
    for (var i = 0; i < newPlugins.length; i++) {
        var s = newPlugins[i];
        try{
            if(s){
                owl_app_pluginsService.add(s);
            }

        }
        catch(e){
            $.log("error add plugin:" + JSON.stringify(s) + ",e=" + e);
        }

    }

}


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(!oo){
                    $.log("old obj = null")
                    oo = {};
                }
                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);
    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;
            }
        }

        var app = {
            tableId: appId,
            name: name,
            isWidget: isWidget,
            isHide: isHide,
            project: project,
            pos: pos
        }

        if (group) {
            if (typeof group == 'string') {
                app.groupId = group;
                app.groupName = group;
            } else {
                app.groupId = group.id;
                app.groupName = group.name;
                app.groupPos = group.pos;
            }

        }
        var id = "owl_apps_" + appId;
        var owlapp = owl_appsService.get(id);
        if (owlapp) {
            if (owlapp.name != app.name
                || owlapp.isWidget != app.isWidget
                || owlapp.isHide != app.isHide ||
                owlapp.project != app.project ||
                owlapp.pos != app.pos ||
                owlapp.groupId != app.groupId ||
                owlapp.groupName != app.groupName
                || owlapp.groupPos != app.groupPos) {
                Object.assign(owlapp, app);
                owl_appsService.update(owlapp);
            }

        } else {
            owl_appsService.add(app);
        }

        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);


        //plugins

        var plugins = getPlugins(specObj, appId, app.name);
        var oldPlugins = getOldPlugins(appId);
        var newPlugins = getNewPlugins(plugins, oldPlugins);
        var deletedPlugins = getDeletedPlugins(plugins, oldPlugins);

        removeDeletedPlugins(deletedPlugins);
        addNewPlugins(newPlugins);




    }

    var ret = {
        state: "ok",
        msg: "更新成功"
    }
    out.print(JSON.stringify(ret));


}

main();