import * as fs from 'fs';
import * as path from 'path';
import * as tsickle from 'tsickle';
import * as ts from 'typescript';

import {FileLoader} from './cache';
import * as perfTrace from './perf_trace';
import {BazelOptions} from './tsconfig';
import {DEBUG, debug} from './worker';

export type ModuleResolver =
    (moduleName: string, containingFile: string,
     compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost) =>
        ts.ResolvedModuleWithFailedLookupLocations;

/**
 * Narrows down the type of some properties from non-optional to required, so
 * that we do not need to check presence before each access.
 */
export interface BazelTsOptions extends ts.CompilerOptions {
  rootDirs: string[];
  rootDir: string;
  outDir: string;
  typeRoots: string[];
}

export function narrowTsOptions(options: ts.CompilerOptions): BazelTsOptions {
  if (!options.rootDirs) {
    throw new Error(`compilerOptions.rootDirs should be set by tsconfig.bzl`);
  }
  if (!options.rootDir) {
    throw new Error(`compilerOptions.rootDirs should be set by tsconfig.bzl`);
  }
  if (!options.outDir) {
    throw new Error(`compilerOptions.rootDirs should be set by tsconfig.bzl`);
  }
  return options as BazelTsOptions;
}

function validateBazelOptions(bazelOpts: BazelOptions) {
  if (!bazelOpts.isJsTranspilation) return;

  if (bazelOpts.compilationTargetSrc &&
      bazelOpts.compilationTargetSrc.length > 1) {
    throw new Error("In JS transpilation mode, only one file can appear in " +
                    "bazelOptions.compilationTargetSrc.");
  }

  if (!bazelOpts.transpiledJsOutputFileName) {
    throw new Error("In JS transpilation mode, transpiledJsOutputFileName " +
                    "must be specified in tsconfig.");
  }
}

const TS_EXT = /(\.d)?\.tsx?$/;

/**
 * CompilerHost that knows how to cache parsed files to improve compile times.
 */
export class CompilerHost implements ts.CompilerHost, tsickle.TsickleHost {
  /**
   * Lookup table to answer file stat's without looking on disk.
   */
  private knownFiles = new Set<string>();

  /**
   * rootDirs relative to the rootDir, eg "bazel-out/local-fastbuild/bin"
   */
  private relativeRoots: string[];

  getCancelationToken?: () => ts.CancellationToken;
  directoryExists?: (dir: string) => boolean;

  googmodule: boolean;
  es5Mode: boolean;
  prelude: string;
  untyped: boolean;
  typeBlackListPaths: Set<string>;
  transformDecorators: boolean;
  transformTypesToClosure: boolean;
  addDtsClutzAliases: boolean;
  isJsTranspilation: boolean;
  provideExternalModuleDtsNamespace: boolean;
  options: BazelTsOptions;
  host: ts.ModuleResolutionHost = this;
  private allowActionInputReads = true;


  constructor(
      public inputFiles: string[], options: ts.CompilerOptions,
      readonly bazelOpts: BazelOptions, private delegate: ts.CompilerHost,
      private fileLoader: FileLoader,
      private moduleResolver: ModuleResolver = ts.resolveModuleName) {
    this.options = narrowTsOptions(options);
    this.relativeRoots =
        this.options.rootDirs.map(r => path.relative(this.options.rootDir, r));
    inputFiles.forEach((f) => {
      this.knownFiles.add(f);
    });

    // getCancelationToken is an optional method on the delegate. If we
    // unconditionally implement the method, we will be forced to return null,
    // in the absense of the delegate method. That won't match the return type.
    // Instead, we optionally set a function to a field with the same name.
    if (delegate && delegate.getCancellationToken) {
      this.getCancelationToken = delegate.getCancellationToken.bind(delegate);
    }

    // Override directoryExists so that TypeScript can automatically
    // include global typings from node_modules/@types
    // see getAutomaticTypeDirectiveNames in
    // TypeScript:src/compiler/moduleNameResolver
    if (this.allowActionInputReads && delegate && delegate.directoryExists) {
      this.directoryExists = delegate.directoryExists.bind(delegate);
    }

    validateBazelOptions(bazelOpts);
    this.googmodule = bazelOpts.googmodule;
    this.es5Mode = bazelOpts.es5Mode;
    this.prelude = bazelOpts.prelude;
    this.untyped = bazelOpts.untyped;
    this.typeBlackListPaths = new Set(bazelOpts.typeBlackListPaths);
    this.transformDecorators = bazelOpts.tsickle;
    this.transformTypesToClosure = bazelOpts.tsickle;
    this.addDtsClutzAliases = bazelOpts.addDtsClutzAliases;
    this.isJsTranspilation = Boolean(bazelOpts.isJsTranspilation);
    this.provideExternalModuleDtsNamespace = !bazelOpts.hasImplementation;
  }

  /**
   * For the given potentially absolute input file path (typically .ts), returns
   * the relative output path. For example, for
   * /path/to/root/blaze-out/k8-fastbuild/genfiles/my/file.ts, will return
   * my/file.js or my/file.closure.js (depending on ES5 mode).
   */
  relativeOutputPath(fileName: string) {
    let result = this.rootDirsRelative(fileName);
    result = result.replace(/(\.d)?\.[jt]sx?$/, '');
    if (!this.bazelOpts.es5Mode) result += '.closure';
    return result + '.js';
  }

  /**
   * Workaround https://github.com/Microsoft/TypeScript/issues/8245
   * We use the `rootDirs` property both for module resolution,
   * and *also* to flatten the structure of the output directory
   * (as `rootDir` would do for a single root).
   * To do this, look for the pattern outDir/relativeRoots[i]/path/to/file
   * or relativeRoots[i]/path/to/file
   * and replace that with path/to/file
   */
  flattenOutDir(fileName: string): string {
    let result = fileName;

    // outDir/relativeRoots[i]/path/to/file -> relativeRoots[i]/path/to/file
    if (fileName.startsWith(this.options.rootDir)) {
      result = path.relative(this.options.outDir, fileName);
    }

    for (const dir of this.relativeRoots) {
      // relativeRoots[i]/path/to/file -> path/to/file
      const rel = path.relative(dir, result);
      if (!rel.startsWith('..')) {
        result = rel;
        // relativeRoots is sorted longest first so we can short-circuit
        // after the first match
        break;
      }
    }
    return result;
  }

  /** Avoid using tsickle on files that aren't in srcs[] */
  shouldSkipTsickleProcessing(fileName: string): boolean {
    return this.bazelOpts.isJsTranspilation ||
           this.bazelOpts.compilationTargetSrc.indexOf(fileName) === -1;
  }

  /** Whether the file is expected to be imported using a named module */
  shouldNameModule(fileName: string): boolean {
    return this.bazelOpts.compilationTargetSrc.indexOf(fileName) !== -1;
  }

  /** Allows suppressing warnings for specific known libraries */
  shouldIgnoreWarningsForPath(filePath: string): boolean {
    return this.bazelOpts.ignoreWarningPaths.some(
        p => !!filePath.match(new RegExp(p)));
  }

  /**
   * fileNameToModuleId gives the module ID for an input source file name.
   * @param fileName an input source file name, e.g.
   *     /root/dir/bazel-out/host/bin/my/file.ts.
   * @return the canonical path of a file within blaze, without /genfiles/ or
   *     /bin/ path parts, excluding a file extension. For example, "my/file".
   */
  fileNameToModuleId(fileName: string): string {
    return this.relativeOutputPath(
        fileName.substring(0, fileName.lastIndexOf('.')));
  }

  /**
   * TypeScript SourceFile's have a path with the rootDirs[i] still present, eg.
   * /build/work/bazel-out/local-fastbuild/bin/path/to/file
   * @return the path without any rootDirs, eg. path/to/file
   */
  private rootDirsRelative(fileName: string): string {
    for (const root of this.options.rootDirs) {
      if (fileName.startsWith(root)) {
        // rootDirs are sorted longest-first, so short-circuit the iteration
        // see tsconfig.ts.
        return path.posix.relative(root, fileName);
      }
    }
    return fileName;
  }

  /**
   * Massages file names into valid goog.module names:
   * - resolves relative paths to the given context
   * - resolves non-relative paths which takes module_root into account
   * - replaces '/' with '.' in the '<workspace>' namespace
   * - replace first char if non-alpha
   * - replace subsequent non-alpha numeric chars
   */
  pathToModuleName(context: string, importPath: string): string {
    // tsickle hands us an output path, we need to map it back to a source
    // path in order to do module resolution with it.
    // outDir/relativeRoots[i]/path/to/file ->
    // rootDir/relativeRoots[i]/path/to/file
    if (context.startsWith(this.options.outDir)) {
      context = path.join(
          this.options.rootDir, path.relative(this.options.outDir, context));
    }

    // Try to get the resolved path name from TS compiler host which can
    // handle resolution for libraries with module_root like rxjs and @angular.
    let resolvedPath: string|null = null;
    const resolved =
        this.moduleResolver(importPath, context, this.options, this);
    if (resolved && resolved.resolvedModule &&
        resolved.resolvedModule.resolvedFileName) {
      resolvedPath = resolved.resolvedModule.resolvedFileName;
      // /build/work/bazel-out/local-fastbuild/bin/path/to/file ->
      // path/to/file
      resolvedPath = this.rootDirsRelative(resolvedPath);
    } else {
      // importPath can be an absolute file path in google3.
      // Try to trim it as a path relative to bin and genfiles, and if so,
      // handle its file extension in the block below and prepend the workspace
      // name.
      const trimmed = this.rootDirsRelative(importPath);
      if (trimmed !== importPath) {
        resolvedPath = trimmed;
      }
    }
    if (resolvedPath) {
      // Strip file extensions.
      importPath = resolvedPath.replace(TS_EXT, '');
      // Make sure all module names include the workspace name.
      if (importPath.indexOf(this.bazelOpts.workspaceName) !== 0) {
        importPath = path.posix.join(this.bazelOpts.workspaceName, importPath);
      }
    }

    // Remove the __{LOCALE} from the module name.
    if (this.bazelOpts.locale) {
      const suffix = '__' + this.bazelOpts.locale.toLowerCase();
      if (importPath.toLowerCase().endsWith(suffix)) {
        importPath = importPath.substring(0, importPath.length - suffix.length);
      }
    }

    // Replace characters not supported by goog.module and '.' with
    // '$<Hex char code>' so that the original module name can be re-obtained
    // without any loss.
    // See goog.VALID_MODULE_RE_ in Closure's base.js for characters supported
    // by google.module.

    const escape = (c: string) => {
      return '$' + c.charCodeAt(0).toString(16);
    };
    const moduleName = importPath.replace(/^[^a-zA-Z_/]/, escape)
                           .replace(/[^a-zA-Z_0-9_/]/g, escape)
                           .replace(/\//g, '.');
    return moduleName;
  }

  /**
   * Converts file path into a valid AMD module name.
   *
   * An AMD module can have an arbitrary name, so that it is require'd by name
   * rather than by path. See http://requirejs.org/docs/whyamd.html#namedmodules
   *
   * "However, tools that combine multiple modules together for performance need
   *  a way to give names to each module in the optimized file. For that, AMD
   *  allows a string as the first argument to define()"
   */
  amdModuleName(sf: ts.SourceFile): string|undefined {
    if (!this.shouldNameModule(sf.fileName)) return undefined;
    // /build/work/bazel-out/local-fastbuild/bin/path/to/file.ts
    // -> path/to/file
    let fileName = this.rootDirsRelative(sf.fileName).replace(TS_EXT, '');

    let workspace = this.bazelOpts.workspaceName;

    // Workaround https://github.com/bazelbuild/bazel/issues/1262
    //
    // When the file comes from an external bazel repository,
    // and TypeScript resolves runfiles symlinks, then the path will look like
    // output_base/execroot/local_repo/external/another_repo/foo/bar
    // We want to name such a module "another_repo/foo/bar" just as it would be
    // named by code in that repository.
    // As a workaround, check for the /external/ path segment, and fix up the
    // workspace name to be the name of the external repository.
    if (fileName.startsWith('external/')) {
      const parts = fileName.split('/');
      workspace = parts[1];
      fileName = parts.slice(2).join('/');
    }

    if (this.bazelOpts.moduleName) {
      const relativeFileName = path.posix.relative(this.bazelOpts.package, fileName);
      if (!relativeFileName.startsWith('..')) {
        if (this.bazelOpts.moduleRoot &&
            this.bazelOpts.moduleRoot.replace(TS_EXT, '') ===
                relativeFileName) {
          return this.bazelOpts.moduleName;
        }
        // Support the common case of commonjs convention that index is the
        // default module in a directory.
        // This makes our module naming scheme more conventional and lets users
        // refer to modules with the natural name they're used to.
        if (relativeFileName === 'index') {
          return this.bazelOpts.moduleName;
        }
        return path.posix.join(this.bazelOpts.moduleName, relativeFileName);
      }
    }

    // path/to/file ->
    // myWorkspace/path/to/file
    return path.posix.join(workspace, fileName);
  }

  // Resolves the typings file from a package at the specified path.
  // Helper function to `resolveTypeReferenceDirectives`.
  private resolveTypingFromDirectory(typePath: string, primary: boolean): ts.ResolvedTypeReferenceDirective | undefined {
    // Looks for the `typings` attribute in a package.json file
    // if it exists
    const pkgFile = path.posix.join(typePath, 'package.json');
    if (this.fileExists(pkgFile)) {
      const pkg = JSON.parse(fs.readFileSync(pkgFile, 'UTF-8'));
      let typings = pkg['typings'];
      if (typings) {
        if (typings === '.' || typings === './') {
          typings = 'index.d.ts';
        }
        const maybe = path.posix.join(typePath, typings);
        if (this.fileExists(maybe)) {
          return { primary, resolvedFileName: maybe };
        }
      }
    }

    // Look for an index.d.ts file in the path
    const maybe = path.posix.join(typePath, 'index.d.ts');
    if (this.fileExists(maybe)) {
      return { primary, resolvedFileName: maybe };
    }

    return undefined;
  }

  // Override the default typescript resolveTypeReferenceDirectives function.
  // Resolves /// <reference types="x" /> directives under bazel.
  // The default typescript secondary search behavior needs to be overridden
  // to support looking under `bazelOpts.nodeModulesPrefix`
  resolveTypeReferenceDirectives(names: string[], containingFile: string): (ts.ResolvedTypeReferenceDirective | undefined)[] {
    let result: (ts.ResolvedTypeReferenceDirective | undefined)[] = []
    names.forEach(name => {
      let resolved: ts.ResolvedTypeReferenceDirective | undefined;

      // primary search
      this.options.typeRoots.forEach(typeRoot => {
        if (!resolved) {
          resolved = this.resolveTypingFromDirectory(path.posix.join(typeRoot, name), true);
        }
      });

      // secondary search
      if (!resolved) {
        resolved = this.resolveTypingFromDirectory(path.posix.join(this.bazelOpts.nodeModulesPrefix, name), false);
      }

      // Types not resolved should be silently ignored. Leave it to Typescript
      // to either error out with "TS2688: Cannot find type definition file for
      // 'foo'" or for the build to fail due to a missing type that is used.
      if (DEBUG && !resolved) {
        debug(`Failed to resolve type reference directive '${name}'`);
      }

      result.push(resolved);
    });
    return result;
  }

  /** Loads a source file from disk (or the cache). */
  getSourceFile(
      fileName: string, languageVersion: ts.ScriptTarget,
      onError?: (message: string) => void) {
    return perfTrace.wrap(`getSourceFile ${fileName}`, () => {
      const sf = this.fileLoader.loadFile(fileName, fileName, languageVersion);
      if (!/\.d\.tsx?$/.test(fileName) &&
          (this.options.module === ts.ModuleKind.AMD ||
           this.options.module === ts.ModuleKind.UMD)) {
        const moduleName = this.amdModuleName(sf);
        if (sf.moduleName === moduleName || !moduleName) return sf;
        if (sf.moduleName) {
          throw new Error(
              `ERROR: ${sf.fileName} ` +
              `contains a module name declaration ${sf.moduleName} ` +
              `which would be overwritten with ${moduleName} ` +
              `by Bazel's TypeScript compiler.`);
        }
        // Setting the moduleName is equivalent to the original source having a
        // ///<amd-module name="some/name"/> directive
        sf.moduleName = moduleName;
      }
      return sf;
    });
  }

  writeFile(
      fileName: string, content: string, writeByteOrderMark: boolean,
      onError: ((message: string) => void) | undefined,
      sourceFiles: ReadonlyArray<ts.SourceFile>): void {
    perfTrace.wrap(
        `writeFile ${fileName}`,
        () => this.writeFileImpl(
            fileName, content, writeByteOrderMark, onError, sourceFiles || []));
  }

  writeFileImpl(
      fileName: string, content: string, writeByteOrderMark: boolean,
      onError: ((message: string) => void) | undefined,
      sourceFiles: ReadonlyArray<ts.SourceFile>): void {
    // Workaround https://github.com/Microsoft/TypeScript/issues/18648
    // This bug is fixed in TS 2.9
    const version = ts.versionMajorMinor;
    const [major, minor] = version.split('.').map(s => Number(s));
    const workaroundNeeded = major <= 2 && minor <= 8;
    if (workaroundNeeded &&
        (this.options.module === ts.ModuleKind.AMD ||
         this.options.module === ts.ModuleKind.UMD) &&
        fileName.endsWith('.d.ts') && sourceFiles && sourceFiles.length > 0 &&
        sourceFiles[0].moduleName) {
      content =
          `/// <amd-module name="${sourceFiles[0].moduleName}" />\n${content}`;
    }
    fileName = this.flattenOutDir(fileName);

    if (this.bazelOpts.isJsTranspilation) {
      fileName = this.bazelOpts.transpiledJsOutputFileName!;
    } else if (!this.bazelOpts.es5Mode) {
      // Write ES6 transpiled files to *.closure.js.
      if (this.bazelOpts.locale) {
        // i18n paths are required to end with __locale.js so we put
        // the .closure segment before the __locale
        fileName = fileName.replace(/(__[^\.]+)?\.js$/, '.closure$1.js');
      } else {
        fileName = fileName.replace(/\.js$/, '.closure.js');
      }
    }

    // Prepend the output directory.
    fileName = path.join(this.options.outDir, fileName);

    // Our file cache is based on mtime - so avoid writing files if they
    // did not change.
    if (!fs.existsSync(fileName) ||
        fs.readFileSync(fileName, 'utf-8') !== content) {
      this.delegate.writeFile(
          fileName, content, writeByteOrderMark, onError, sourceFiles);
    }
  }

  /**
   * Performance optimization: don't try to stat files we weren't explicitly
   * given as inputs.
   * This also allows us to disable Bazel sandboxing, without accidentally
   * reading .ts inputs when .d.ts inputs are intended.
   * Note that in worker mode, the file cache will also guard against arbitrary
   * file reads.
   */
  fileExists(filePath: string): boolean {
    // Under Bazel, users do not declare deps[] on their node_modules.
    // This means that we do not list all the needed .d.ts files in the files[]
    // section of tsconfig.json, and that is what populates the knownFiles set.
    // In addition, the node module resolver may need to read package.json files
    // and these are not permitted in the files[] section.
    // So we permit reading node_modules/* from action inputs, even though this
    // can include data[] dependencies and is broader than we would like.
    // This should only be enabled under Bazel, not Blaze.
    if (this.allowActionInputReads && filePath.indexOf('/node_modules/') >= 0) {
      const result = this.fileLoader.fileExists(filePath);
      if (DEBUG && !result && this.delegate.fileExists(filePath)) {
        debug("Path exists, but is not registered in the cache", filePath);
        Object.keys((this.fileLoader as any).cache.lastDigests).forEach(k => {
          if (k.endsWith(path.basename(filePath))) {
            debug("  Maybe you meant to load from", k);
          }
        });
      }
      return result;
    }
    return this.knownFiles.has(filePath);
  }

  // Since we override getDefaultLibFileName below, we must also provide the
  // directory containing the file.
  // Otherwise TypeScript looks in C:\lib.xxx.d.ts for the default lib.
  getDefaultLibLocation(): string {
    return path.dirname(
        this.getDefaultLibFileName({target: ts.ScriptTarget.ES5}));
  }

  getDefaultLibFileName(options: ts.CompilerOptions): string {
    if (this.bazelOpts.nodeModulesPrefix) {
      return path.join(
          this.bazelOpts.nodeModulesPrefix, 'typescript/lib',
          ts.getDefaultLibFileName({target: ts.ScriptTarget.ES5}));
    }
    return this.delegate.getDefaultLibFileName(options);
  }

  realpath(s: string): string {
    // tsc-wrapped relies on string matching of file paths for things like the
    // file cache and for strict deps checking.
    // TypeScript will try to resolve symlinks during module resolution which
    // makes our checks fail: the path we resolved as an input isn't the same
    // one the module resolver will look for.
    // See https://github.com/Microsoft/TypeScript/pull/12020
    // So we simply turn off symlink resolution.
    return s;
  }

  // Delegate everything else to the original compiler host.

  getCanonicalFileName(path: string) {
    return this.delegate.getCanonicalFileName(path);
  }

  getCurrentDirectory(): string {
    return this.delegate.getCurrentDirectory();
  }

  useCaseSensitiveFileNames(): boolean {
    return this.delegate.useCaseSensitiveFileNames();
  }

  getNewLine(): string {
    return this.delegate.getNewLine();
  }

  getDirectories(path: string) {
    return this.delegate.getDirectories(path);
  }

  readFile(fileName: string): string|undefined {
    return this.delegate.readFile(fileName);
  }

  trace(s: string): void {
    console.error(s);
  }
}
