#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCustomTypes = void 0;
const chalk_1 = __importDefault(require("chalk"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const prettier_1 = __importDefault(require("prettier"));
const xml2js_1 = __importDefault(require("xml2js"));
async function generateCustomTypes(extensions) {
    let typeExtensions = await parseMeta(extensions);
    let attrspath = path_1.default.join(__dirname, '../@types/sfcc/attrs.txt');
    console.log('path is ' + attrspath);
    let customObjList = new Set(fs_1.default.readFileSync(attrspath, 'utf8').split('\n'));
    let customattrsrc = Array.from(typeExtensions).filter(i => i.attributedefinitions && i.attributedefinitions.length > 0).map((i) => {
        let typename = i.typeid;
        customObjList.delete(typename);
        return `
/**
 * Custom attributes for ${typename} object.
 */
declare class ${typename}CustomAttributes {

  ${i.attributedefinitions.map(at => mapAttribute(at)).join('\n')}
}`;
    }).join('\n');
    customattrsrc += Array.from(customObjList).map((typename) => {
        return `
/**
 * Custom attributes for ${typename} object.
 */
declare class ${typename}CustomAttributes {
  /**
   * Returns the custom attribute with this name. Throws an exception if attribute is not defined
   */
  [name: string]: any;
}`;
    }).join('\n');
    let out = customattrsrc;
    let outpath = path_1.default.join('@types/dw', "attrs.d.ts");
    let prettierconfig = {};
    if (fs_1.default.existsSync('.prettierrc')) {
        try {
            prettierconfig = JSON.parse(fs_1.default.readFileSync('.prettierrc', 'utf8'));
        }
        catch (e) {
            console.log(chalk_1.default.red(`Unable to parse local .prettierrc: ${e}`));
        }
    }
    prettierconfig.parser = "typescript";
    prettierconfig.proseWrap = 'always';
    try {
        out = prettier_1.default.format(customattrsrc, prettierconfig);
    }
    catch (e) {
        console.error(chalk_1.default.red(`Prettier format failed, check generated file at ${outpath}\n${e}`));
    }
    fs_1.default.writeFileSync(outpath, out);
}
exports.generateCustomTypes = generateCustomTypes;
function mapAttribute(at) {
    return `/**
  * ${at.description || at.displayname || ''}
  */
 ${at.attributeid.indexOf('-') > -1 ? "'" + at.attributeid + "'" : at.attributeid}: ${remapType(at)};

 `;
}
function remapType(at) {
    if (at.type === 'string' || at.type === 'text' || at.type === 'password' || at.type === 'email') {
        return 'string';
    }
    if (at.type === 'double' || at.type === 'int') {
        return 'number';
    }
    if (at.type === 'set-of-string') {
        return 'string[]';
    }
    if (at.type === 'set-of-int') {
        return 'number[]';
    }
    if (at.type === 'date' || at.type === 'datetime') {
        return 'Date';
    }
    if (at.type === 'enum-of-int' || at.type === 'enum-of-double') {
        return (at.valuedefinitions || [{ value: 0 }]).map(v => v.value).join(' | ');
    }
    if (at.type === 'enum-of-string') {
        return (at.valuedefinitions || [{ value: '' }]).map(v => `'${v.value}'`).join(' | ');
    }
    if (at.type === 'image') {
        return 'dw.content.MediaFile';
    }
    if (at.type === 'html') {
        return 'dw.content.MarkupText';
    }
    return at.type;
}
async function parseMeta(source) {
    var parser = new xml2js_1.default.Parser({
        trim: true,
        normalizeTags: true,
        mergeAttrs: true,
        explicitArray: false,
        attrNameProcessors: [function (name) { return name.replace(/-/g, ''); }],
        tagNameProcessors: [function (name) { return name.replace(/-/g, ''); }]
    });
    let exts = await parser.parseStringPromise(fs_1.default.readFileSync(source, 'utf-8'));
    if (exts.metadata && exts.metadata.typeextension) {
        ensureArray(exts.metadata, 'typeextension');
        exts = exts.metadata.typeextension.map((i) => cleanupEntry(i)).filter((i) => i.attributedefinitions);
    }
    cleanI18n(exts);
    // fs.writeFileSync(path.join(process.cwd(), `${path.basename(source)}.json`), JSON.stringify(exts, null, 2));
    return exts;
}
function ensureArray(object, field) {
    if (object && object[field] && !object[field].length) {
        object[field] = [object[field]];
    }
}
function cleanupEntry(i) {
    let res = i;
    // normalize
    if (res.customattributedefinitions) {
        res.attributedefinitions = res.customattributedefinitions;
        delete res.customattributedefinitions;
    }
    delete res.systemattributedefinitions;
    // cleanup single attributes without array
    if (res.attributedefinitions && res.attributedefinitions.attributedefinition && res.attributedefinitions.attributedefinition.attributeid) {
        res.attributedefinitions.attributedefinition = [res.attributedefinitions.attributedefinition];
    }
    if (res.attributedefinitions && res.attributedefinitions.attributedefinition) {
        res.attributedefinitions = res.attributedefinitions.attributedefinition;
        res.attributedefinitions.forEach((ad) => {
            if (ad.valuedefinitions) {
                ad.valuedefinitions = ad.valuedefinitions.valuedefinition;
                ensureArray(ad, 'valuedefinitions');
            }
        });
        if (res.attributedefinitions.valuedefinitions) {
        }
    }
    return res;
}
function cleanI18n(obj) {
    Object
        .entries(obj)
        .forEach(entry => {
        let [k, v] = entry;
        if (v !== null && typeof v === 'object' && !v.escape) {
            if (v._ && v['xml:lang'] && Object.keys(v).length === 2) {
                obj[k] = v._;
                // log(`-> replaced ${obj[k]}`);
            }
            cleanI18n(v);
        }
    });
}
