/**
 * @license
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as fs from "fs";
import * as parse5 from "parse5";
import * as dom5 from "dom5";
import * as path from "path";
import {Node} from 'dom5';
import {fail, unexpectedSwitchValue} from "../utils/common";
import {readMultilineParamFile} from "../utils/command-line";
import {
  HtmlSrcFilePath,
  JsSrcFilePath,
  HtmlTargetFilePath,
  JsTargetFilePath,
  FileUtils,
  FilePath
} from "../utils/file-utils";
import {
  AbsoluteWebPath,
  getRelativeImport,
  NodeModuleImportPath,
  SrcWebSite
} from "../utils/web-site-utils";

/**
 * Update source code by moving all scripts out of HTML files.
 * Input:
 *   input_output_html_param_file - list of file paths, each file path on a separate line
 *      The first 3 line contains the path to the first input HTML file and 2 output paths
 *         (for HTML and JS files)
 *      The second 3 line contains paths for the second HTML file, and so on.
 *
 *   input_output_js_param_file - similar to input_output_html_param_file, but has only 2 lines
 *      per file (input JS file and output JS file)
 *
 *   input_web_root_path - path (in filesystem) which should be treated as a web-site root path.

 *    For each HTML file it creates 2 output files - HTML and JS file.
 *      HTML file contains everything from HTML input file, except <script> tags.
 *      JS file contains (in the same order, as in original HTML):
 *      - inline javascript code from HTML file
 *      - each <script src = "path/to/file.js" > from HTML is converted to
 *           import 'path/to/output/file.js'
 *        statement. Such import statement run all side-effects in file.js (i.e. it run all    #
 *        global code).
 *      - each <link rel="import" href = "path/to/file.html"> adds to .js file as
 *           import 'path/to/output/file.html.js
 *        i.e. instead of html, the .js script imports
 *    Because output JS keeps the order of imports, all global variables are
 *    initialized in a correct order (this is important for gerrit; it is impossible to use
 *    AMD modules here).
 */

enum RefType {
  Html,
  InlineJS,
  JSFile
}

type LinkOrScript = HtmlFileRef | HtmlFileNodeModuleRef | JsFileReference | JsFileNodeModuleReference | InlineJS;

interface HtmlFileRef {
  type: RefType.Html,
  path: HtmlSrcFilePath;
  isNodeModule: false;
}

interface HtmlFileNodeModuleRef {
  type: RefType.Html,
  path: NodeModuleImportPath;
  isNodeModule: true;
}


function isHtmlFileRef(ref: LinkOrScript): ref is HtmlFileRef {
  return ref.type === RefType.Html;
}

interface JsFileReference {
  type: RefType.JSFile,
  path: JsSrcFilePath;
  isModule: boolean;
  isNodeModule: false;
}

interface JsFileNodeModuleReference {
  type: RefType.JSFile,
  path: NodeModuleImportPath;
  isModule: boolean;
  isNodeModule: true;
}

interface InlineJS {
  type: RefType.InlineJS,
  isModule: boolean;
  content: string;
}

interface HtmlOutputs {
  html: HtmlTargetFilePath;
  js: JsTargetFilePath;
}

interface JsOutputs {
  js: JsTargetFilePath;
}

type HtmlSrcToOutputMap = Map<HtmlSrcFilePath, HtmlOutputs>;
type JsSrcToOutputMap = Map<JsSrcFilePath, JsOutputs>;

interface HtmlFileInfo {
  src: HtmlSrcFilePath;
  ast: parse5.AST.Document;
  linksAndScripts: LinkOrScript[]
}

/** HtmlScriptAndLinksCollector walks through HTML file and collect
 * all links and inline scripts.
 */
class HtmlScriptAndLinksCollector {
  public constructor(private readonly webSite: SrcWebSite) {
  }
  public collect(src: HtmlSrcFilePath): HtmlFileInfo {
    const ast = HtmlScriptAndLinksCollector.getAst(src);
    const isHtmlImport = (node: Node) => node.tagName == "link" &&
        dom5.getAttribute(node, "rel") == "import";
    const isScriptTag = (node: Node) => node.tagName == "script";

    const linksAndScripts: LinkOrScript[] = dom5
      .nodeWalkAll(ast as Node, (node) => isHtmlImport(node) || isScriptTag(node))
      .map((node) => {
        if (isHtmlImport(node)) {
          const href = dom5.getAttribute(node, "href");
          if (!href) {
            fail(`Tag <link rel="import...> in the file '${src}' doesn't have href attribute`);
          }
          if(this.webSite.isNodeModuleReference(href)) {
            return {
              type: RefType.Html,
              path: this.webSite.getNodeModuleImport(href),
              isNodeModule: true,
            }
          } else {
            return {
              type: RefType.Html,
              path: this.webSite.resolveHtmlImport(src, href),
              isNodeModule: false,
            }
          }
        } else {
          const isModule = dom5.getAttribute(node, "type") === "module";
          if (dom5.hasAttribute(node, "src")) {
            let srcPath = dom5.getAttribute(node, "src")!;
            if(this.webSite.isNodeModuleReference(srcPath)) {
              return {
                type: RefType.JSFile,
                isModule: isModule,
                path: this.webSite.getNodeModuleImport(srcPath),
                isNodeModule: true
              };
            } else {
              return {
                type: RefType.JSFile,
                isModule: isModule,
                path: this.webSite.resolveScriptSrc(src, srcPath),
                isNodeModule: false
              };
            }
          }
          return {
            type: RefType.InlineJS,
            isModule: isModule,
            content: dom5.getTextContent(node)
          };
        }
      });
    return {
      src,
      ast,
      linksAndScripts
    };
  };

  private static getAst(file: string): parse5.AST.Document {
    const html = fs.readFileSync(file, "utf-8");
    return parse5.parse(html, {locationInfo: true});
  }

}

/** Generate js files */
class ScriptGenerator {
  public constructor(private readonly pathMapper: SrcToTargetPathMapper) {
  }
  public generateFromJs(src: JsSrcFilePath) {
    FileUtils.copyFile(src, this.pathMapper.getJsTargetForJs(src));
  }

  public generateFromHtml(html: HtmlFileInfo) {
    const content: string[] = [];
    const src = html.src;
    const targetJsFile: JsTargetFilePath = this.pathMapper.getJsTargetForHtml(src);
    html.linksAndScripts.forEach((linkOrScript) => {
      switch (linkOrScript.type) {
        case RefType.Html:
          if(linkOrScript.isNodeModule) {
            const importPath = this.pathMapper.getJsTargetForHtmlInNodeModule(linkOrScript.path)
            content.push(`import '${importPath}';`);
          } else {
            const importPath = this.pathMapper.getJsTargetForHtml(linkOrScript.path);
            const htmlRelativePath = getRelativeImport(targetJsFile, importPath);
            content.push(`import '${htmlRelativePath}';`);
          }
          break;
        case RefType.JSFile:
          if(linkOrScript.isNodeModule) {
            content.push(`import '${linkOrScript.path}'`);
          } else {
            const importFromJs = this.pathMapper.getJsTargetForJs(linkOrScript.path);
            const scriptRelativePath = getRelativeImport(targetJsFile, importFromJs);
            content.push(`import '${scriptRelativePath}';`);
          }
          break;
        case RefType.InlineJS:
          content.push(linkOrScript.content);
          break;
        default:
          unexpectedSwitchValue(linkOrScript);
      }
    });
    FileUtils.writeContent(targetJsFile, content.join("\n"));
  }
}

/** Generate html files*/
class HtmlGenerator {
  constructor(private readonly pathMapper: SrcToTargetPathMapper) {
  }
  public generateFromHtml(html: HtmlFileInfo) {
    const ast = html.ast;
    dom5.nodeWalkAll(ast as Node, (node) => node.tagName === "script")
      .forEach((scriptNode) => dom5.remove(scriptNode));
    const newContent = parse5.serialize(ast);
    if(newContent.indexOf("<script") >= 0) {
      fail(`Has content ${html.src}`);
    }
    FileUtils.writeContent(this.pathMapper.getHtmlTargetForHtml(html.src), newContent);
  }
}

function readHtmlSrcToTargetMap(paramFile: string): HtmlSrcToOutputMap {
  const htmlSrcToTarget: HtmlSrcToOutputMap = new Map();
  const input = readMultilineParamFile(paramFile);
  for(let i = 0; i < input.length; i += 3) {
    const srcHtmlFile = path.resolve(input[i]) as HtmlSrcFilePath;
    const targetHtmlFile = path.resolve(input[i + 1]) as HtmlTargetFilePath;
    const targetJsFile = path.resolve(input[i + 2]) as JsTargetFilePath;
    htmlSrcToTarget.set(srcHtmlFile, {
      html: targetHtmlFile,
      js: targetJsFile
    });
  }
  return htmlSrcToTarget;
}

function readJsSrcToTargetMap(paramFile: string): JsSrcToOutputMap {
  const jsSrcToTarget: JsSrcToOutputMap = new Map();
  const input = readMultilineParamFile(paramFile);
  for(let i = 0; i < input.length; i += 2) {
    const srcJsFile = path.resolve(input[i]) as JsSrcFilePath;
    const targetJsFile = path.resolve(input[i + 1]) as JsTargetFilePath;
    jsSrcToTarget.set(srcJsFile as JsSrcFilePath, {
      js: targetJsFile as JsTargetFilePath
    });
  }
  return jsSrcToTarget;
}

class SrcToTargetPathMapper {
  public constructor(
      private readonly htmlSrcToTarget: HtmlSrcToOutputMap,
      private readonly jsSrcToTarget: JsSrcToOutputMap) {
  }
  public getJsTargetForHtmlInNodeModule(file: NodeModuleImportPath): JsTargetFilePath {
    return `${file}_gen.js` as JsTargetFilePath;
  }

  public getJsTargetForHtml(html: HtmlSrcFilePath): JsTargetFilePath {
    return this.getHtmlOutputs(html).js;
  }
  public getHtmlTargetForHtml(html: HtmlSrcFilePath): HtmlTargetFilePath {
    return this.getHtmlOutputs(html).html;
  }
  public getJsTargetForJs(js: JsSrcFilePath): JsTargetFilePath {
    return this.getJsOutputs(js).js;
  }

  private getHtmlOutputs(html: HtmlSrcFilePath): HtmlOutputs {
    if(!this.htmlSrcToTarget.has(html)) {
      fail(`There are no outputs for the file '${html}'`);
    }
    return this.htmlSrcToTarget.get(html)!;
  }
  private getJsOutputs(js: JsSrcFilePath): JsOutputs {
    if(!this.jsSrcToTarget.has(js)) {
      fail(`There are no outputs for the file '${js}'`);
    }
    return this.jsSrcToTarget.get(js)!;
  }
}

function main() {
  if(process.argv.length < 5) {
    const execFileName = path.basename(__filename);
    fail(`Usage:\nnode ${execFileName} input_web_root_path input_output_html_param_file input_output_js_param_file\n`);
  }

  const srcWebSite = new SrcWebSite(path.resolve(process.argv[2]) as FilePath);
  const htmlSrcToTarget: HtmlSrcToOutputMap = readHtmlSrcToTargetMap(process.argv[3]);
  const jsSrcToTarget: JsSrcToOutputMap = readJsSrcToTargetMap(process.argv[4]);
  const pathMapper = new SrcToTargetPathMapper(htmlSrcToTarget, jsSrcToTarget);

  const scriptGenerator = new ScriptGenerator(pathMapper);
  const htmlGenerator = new HtmlGenerator(pathMapper);
  const scriptAndLinksCollector = new HtmlScriptAndLinksCollector(srcWebSite);

  htmlSrcToTarget.forEach((targets, src) => {
    const htmlFileInfo = scriptAndLinksCollector.collect(src);
    scriptGenerator.generateFromHtml(htmlFileInfo);
    htmlGenerator.generateFromHtml(htmlFileInfo);
  });
  jsSrcToTarget.forEach((targets, src) => {
    scriptGenerator.generateFromJs(src);
  });
}

main();
