/*
 * to save schema for Krutikov and also to update schema or output summary to check number's usage
 * 
 * A.Omelianchuk, 01-jun-2021
 *
 
*/

// var schema; // read elsewhere

/* uses PODS structures for easy C / C# reading
 */

var convertorPresent = 1;

function convert4ramazan() {
  let ns = {};
  for (let t in schema.unitTypes) {
    let td = schema.unitTypes[t];
    if (td.__.number && ((td.status && td.status.unified) || (td.event && td.event.code))) {
      let nt = {};
      if (td.status && td.status.unified) nt.status = td.status.unified;
      if (td.event && td.event.code) nt.event = td.event.code;
      nt.TitleRU = td.__.TitleRU;
      nt.DescriptionRU = td.__.DescriptionRU;
      ns[t] = nt;
    }
  }
  return ns;
}

function convert4krutikov() {
  let changedSchema = false;
  let nnn = maxNumberUsed; /////////
  if (nnn < 60) nnn = 60;

  let ns = {
    unitTypes: [],
    languages: schema.languages,
  };

  if (schema.categories) {
    ns.categories = [];
    for (let c in schema.categories) {
      let n = { name: c };
      for (let p in schema.categories[c]) n[p] = schema.categories[c][p];
      ns.categories.push(n);
    }
  }

  for (let ut in schema.unitTypes) {
    let ud = schema.unitTypes[ut];

    let nu = { name: ut, messages: [], Title: [], Description: [] };
    for (let pn in ud.__) {
      if (pn.startsWith('Title')) nu.Title.push({ lang: pn.substring(5), name: ud.__[pn] });
      else if (pn.startsWith('Description'))
        nu.Description.push({
          lang: pn.substring(11),
          name: ud.__[pn],
        });
      else if (pn == 'subUnits') {
        nu.subUnits = [];
        for (let sun in ud.__[pn]) {
          let nsud = { name: sun, Title: [], Description: [] };
          let sud = ud.__[pn][sun];
          for (let pn in sud)
            if (pn.startsWith('Title'))
              nsud.Title.push({
                lang: pn.substring(5),
                name: sud[pn],
              });
            else if (pn.startsWith('Description'))
              nsud.Description.push({
                lang: pn.substring(11),
                name: sud[pn],
              });
            else nsud[pn] = sud[pn];
          if (ud.__[pn][sun].qty && !sud.virtual) nu.subUnits.push(nsud);
        }
      } else nu[pn] = ud.__[pn];
    }
    if (nu.number < 0 || !nu.number) {
      if (ud.__.vNumber) nu.number = ud.__.vNumber;
      else {
        if (!schema2.unitTypes[ut].__) schema2.unitTypes[ut].__ = {};
        nu.vNumber = schema2.unitTypes[ut].__.vNumber = nu.number = nnn++;
        changedSchema = true;
      }
      ////////////////
    }

    for (let mn in ud)
      if (mn !== '__' && !ud[mn].unused) {
        let md = ud[mn];
        let nm = { name: mn, fields: [], Title: [], Description: [] };
        for (let pn in md.__)
          if (pn.startsWith('Title'))
            nm.Title.push({
              lang: pn.substring(5),
              name: md.__[pn],
            });
          else if (pn.startsWith('Description'))
            nm.Description.push({
              lang: pn.substring(11),
              name: md.__[pn],
            });
          else nm[pn] = md.__[pn];
        for (let fn in md)
          if (fn !== '__' && !md[fn].unused) {
            let fd = md[fn];
            let nf = { name: fn, Title: [], Description: [] };
            for (let pn in fd)
              if (pn.startsWith('Title'))
                nf.Title.push({
                  lang: pn.substring(5),
                  name: fd[pn],
                });
              else if (pn.startsWith('Description'))
                nf.Description.push({
                  lang: pn.substring(11),
                  name: fd[pn],
                });
              else if (pn.startsWith('enum')) {
                let cat = fd.categories;
                if (!nf.enum) nf.enum = [];
                let ne = { lang: pn.substring(4), values: [] };
                for (let vv in fd[pn])
                  if (typeof fd[pn][vv] == 'string') {
                    let enn = fd[pn][vv];
                    enn = enn.split(':');
                    let newd = {
                      value: parseInt(vv),
                      name: enn[0],
                      info: enn[1],
                    };
                    if (cat) {
                      if (cat[vv]) newd.category = cat[vv];
                      else newd.category = 'default';
                    }
                    ne.values.push(newd);
                  }
                nf.enum.push(ne);
              } else if (pn == 'categories') {
                nf.categories = [];
                for (let n in fd[pn]) {
                  let ne = {};
                  ne.value = Number(n);
                  ne.category = fd[pn][n];
                  nf.categories.push(ne);
                }
              } else if (pn == 'colors') {
                nf.colors = [];
                for (let n in fd[pn]) {
                  let ne = {};
                  ne.value = Number(n);
                  ne.color = fd[pn][n];
                  nf.colors.push(ne);
                }
              } else nf[pn] = fd[pn];
            nm.fields.push(nf);
          }
        nu.messages.push(nm);
      }
    ns.unitTypes.push(nu);
  }
  if (changedSchema) {
    saveFile(schema2, 'schema2');
  }
  return ns;
}

function saveLang2() {
  if (extSchema) saveFileJSON(extSchema, 'newschema');
}

function saveRamazan() {
  saveFile(convert4ramazan(), 'sch');
}
function saveKrutikov() {
  saveFile(convert4krutikov(), 'sch');
}

function combine2schemasBack() {
  // create schlang - only
  if (!schLang) schLang = {};
  if (!schLang.languages) schLang.languages = [];
  for (let la of schema.languages) if (!schLang.languages.includes(la)) schLang.languages.push(la);

  function fillDict(div) {
    if (!schLang[div]) schLang[div] = {};

    for (let word in schema[div]) {
      if (!schLang[div][word]) schLang[div][word] = schema[div][word];
      for (let la of schema.languages)
        if (!schLang[div][word][la]) {
          if (schema2[div][word][la]) schLang[div][word][la] = schema2[div][word][la];
          else schLang[div][word][la] = '---';
        }
      for (let la of schLang.languages) if (!schLang[div][word][la]) schLang[div][word][la] = '---';
    }
  }

  for (let div of ['dictionary', 'operatorLevels', 'categories']) fillDict(div);

  function fillTD(ud) {
    for (let la of schLang.languages) for (n of ['Title', 'Description']) if (!ud[n + la]) ud[n + la] = '---';
  }

  function combineParamTypes(s, s0) {
    for (let la of schema.languages)
      if (la != 'EN') {
        if (s0.enumEN)
          if (!s['enum' + la]) {
            // main combined schema has it
            s['enum' + la] = {};
            for (let n in s0.enumEN)
              if (s0.enumEN[n] !== null)
                // only not nulled
                s['enum' + la][n] = '---';
          }
        for (let start of ['Title', 'Description']) if (s0[start + 'EN'] && !s[start + la]) s[start + la] = '---';
        fillTD(s);
      }
  }

  if (schema2.paramTypes) {
    // todo - use types
    if (!schLang.paramTypes) schLang.paramTypes = {};
    for (let p in schema2.paramTypes) {
      if (!schLang.paramTypes[p]) schLang.paramTypes[p] = {};
      combineParamTypes(schLang.paramTypes[p], schema2.paramTypes[p]);
    }
  }

  function combineDefines(s, l, s0, lvl) {
    if (l && typeof l == 'object' && s && typeof s == 'object') {
      if (Array.isArray(l)) for (let i = l.length; i--; ) combineDefines(s[i], l[i], s0[i], lvl + 1);
      else
        for (let p in l) {
          if (p.startsWith('Title') || p.startsWith('Description')) {
            if (typeof s[p] != 'string') s[p] = l[p];
          } else if (p.startsWith('enum')) {
            if (!s[p]) s[p] = {};
            for (let n in l[p]) if (l[p][n] !== null && typeof s[p][n] !== 'string') s[p][n] = l[p][n];
          } else if (['number', 'vNumber', 'inherits'].includes(p)) s[p] = l[p];
          else if (typeof l[p] == 'object' && l[p] && !Array.isArray(l[p])) {
            if (!s[p]) s[p] = {};
            combineDefines(s[p], l[p], s0[p], lvl + 1);
            if (!Object.getOwnPropertyNames(s[p]).length) delete s[p];
          }
        }

      combineParamTypes(s, s0);
    }
  }

  if (!schLang.unitTypes) schLang.unitTypes = {};

  combineDefines(schLang.unitTypes, schema2.unitTypes, schema.unitTypes, 0);

  for (let u in schLang.unitTypes) {
    for (let p in schema2.unitTypes[u]) {
      if (!schLang.unitTypes[u][p]) schLang.unitTypes[u][p] = {};
      fillTD(schLang.unitTypes[u][p]);
      if (p[0] != '_') {
        // cmd
        for (let pp in schema2.unitTypes[u][p]) {
          if (!schLang.unitTypes[u][p][pp]) schLang.unitTypes[u][p][pp] = {};
          fillTD(schLang.unitTypes[u][p][pp]);
        }
      }
    }
  }

  function cleanTitles(ud, un, lvl) {
    if (typeof ud != 'object') return;
    if (
      lvl <= 1 ||
      (lvl == 2 && un[0] != '_') ||
      (lvl == 2 && un[0] == '_' && !ud.number && !ud.vNumber) ||
      (lvl == 3 && !ud.number)
    ) {
      for (td of ['Title', 'Description']) for (let nam in ud) if (nam.startsWith(td)) delete ud[nam];
    }
    for (let nam in ud) cleanTitles(ud[nam], nam, lvl + 1);
  }

  cleanTitles(schLang.unitTypes, '00', 0);
}

function saveLang() {
  combine2schemasBack();
  saveFile(schLang, 'schLang');
}
