"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const schematics_1 = require("@angular-devkit/schematics");
const parse5_element_1 = require("@angular/cdk/schematics/utils/parse5-element");
const parse5_1 = require("parse5");
const test_1 = require("@schematics/angular/utility/test");
/** Remove content from specified file. */
function removeContentFromFile(host, filePath) {
    const fileBuffer = host.read(filePath);
    if (!fileBuffer) {
        throw new schematics_1.SchematicsException(`Could not read file for path: ${filePath}.`);
    }
    host.overwrite(filePath, '');
    return true;
}
exports.removeContentFromFile = removeContentFromFile;
/** Appends fragment to the specified file. */
function appendToStartFile(host, filePath, fragment) {
    const fileBuffer = host.read(filePath);
    if (!fileBuffer) {
        throw new schematics_1.SchematicsException(`Could not read file for path: ${filePath}.`);
    }
    const content = fileBuffer.toString();
    if (content.includes(fragment)) {
        return;
    }
    const insertion = `${' '.repeat(0)}${fragment}`;
    let recordedChange;
    recordedChange = host
        .beginUpdate(filePath)
        .insertRight(0, `${insertion}\n`);
    host.commitUpdate(recordedChange);
}
exports.appendToStartFile = appendToStartFile;
/** Appends the given element HTML fragment to the `<body>` element of the specified HTML file. */
function appendHtmlElementToBody(host, htmlFilePath, elementHtml, side = 'right') {
    const htmlFileBuffer = host.read(htmlFilePath);
    if (!htmlFileBuffer) {
        throw new schematics_1.SchematicsException(`Could not read file for path: ${htmlFilePath}`);
    }
    const htmlContent = htmlFileBuffer.toString();
    if (htmlContent.includes(elementHtml)) {
        return;
    }
    const bodyTag = getHtmlBodyTagElement(htmlContent);
    if (!bodyTag) {
        throw Error(`Could not find '<body>' element in HTML file: ${htmlFileBuffer}`);
    }
    // We always have access to the source code location here because the `getHtmlBodyTagElement`
    // function explicitly has the `sourceCodeLocationInfo` option enabled.
    if (bodyTag.sourceCodeLocation.endTag) {
        const endTagOffset = bodyTag.sourceCodeLocation.endTag.startOffset;
        const startTagOffset = bodyTag.sourceCodeLocation.startTag.endOffset;
        const indentationOffset = parse5_element_1.getChildElementIndentation(bodyTag);
        const insertion = `${' '.repeat(indentationOffset)}${elementHtml}`;
        let recordedChange;
        if (side === 'left') {
            recordedChange = host
                .beginUpdate(htmlFilePath)
                .insertLeft(startTagOffset, `${insertion}\n`);
            host.commitUpdate(recordedChange);
        }
        else if (side === 'right') {
            recordedChange = host
                .beginUpdate(htmlFilePath)
                .insertRight(endTagOffset, `${insertion}\n`);
            host.commitUpdate(recordedChange);
        }
    }
}
exports.appendHtmlElementToBody = appendHtmlElementToBody;
/** Adds a class to the body of the document. */
function addBodyClass(host, htmlFilePath, className) {
    const htmlFileBuffer = host.read(htmlFilePath);
    if (!htmlFileBuffer) {
        throw new schematics_1.SchematicsException(`Could not read file for path: ${htmlFilePath}`);
    }
    const htmlContent = htmlFileBuffer.toString();
    const body = getElementByTagName('body', htmlContent);
    if (!body) {
        throw Error(`Could not find <body> element in HTML file: ${htmlFileBuffer}`);
    }
    const classAttribute = body.attrs.find(attribute => attribute.name === 'class');
    if (classAttribute) {
        const hasClass = classAttribute.value.split(' ').map(part => part.trim()).includes(className);
        if (!hasClass) {
            const classAttributeLocation = body.sourceCodeLocation.attrs.class;
            const recordedChange = host
                .beginUpdate(htmlFilePath)
                .insertRight(classAttributeLocation.endOffset - 1, ` ${className}`);
            host.commitUpdate(recordedChange);
        }
    }
    else {
        const recordedChange = host
            .beginUpdate(htmlFilePath)
            .insertRight(body.sourceCodeLocation.startTag.endOffset - 1, ` class="${className}"`);
        host.commitUpdate(recordedChange);
    }
}
exports.addBodyClass = addBodyClass;
/** Parses the given HTML file and returns the body element if available. */
function getHtmlBodyTagElement(htmlContent) {
    return getElementByTagName('body', htmlContent);
}
exports.getHtmlBodyTagElement = getHtmlBodyTagElement;
/** Finds an element by its tag name. */
function getElementByTagName(tagName, htmlContent) {
    const document = parse5_1.parse(htmlContent, { sourceCodeLocationInfo: true });
    const nodeQueue = [...document.childNodes];
    while (nodeQueue.length) {
        const node = nodeQueue.shift();
        if (node.nodeName.toLowerCase() === tagName) {
            console.log('node', node);
            return node;
        }
        else if (node.childNodes) {
            nodeQueue.push(...node.childNodes);
        }
    }
    return null;
}
/**
 * Appends a key: value on a specific environment file
 * @param host Tree
 * @param env The environment to be added (example: prod, staging...)
 * @param appPath application path (/src...)
 * @param key The key to be added
 * @param value The value to be added
 * @return void
*/
function addEnvironmentVar(host, env, appPath, key, value) {
    const environmentFilePath = `${appPath}/environments/environment${(env) ? '.' + env : ''}.ts`;
    const sourceFile = test_1.getFileContent(host, environmentFilePath);
    const keyValue = `
  ${key}: '${value}',`;
    host.overwrite(environmentFilePath, sourceFile.replace('export const environment = {', `export const environment = {${keyValue}`));
}
exports.addEnvironmentVar = addEnvironmentVar;
//# sourceMappingURL=index.js.map