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.rootDir should be set by tsconfig.bzl`);
  }
  if (!options.outDir) {
    throw new Error(`compilerOptions.outDir 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 &&
      !bazelOpts.transpiledJsOutputDirectory) {
    throw new Error(
        'In JS transpilation mode, either transpiledJsOutputFileName or ' +
        'transpiledJsOutputDirectory must be specified in tsconfig.');
  }

  if (bazelOpts.transpiledJsOutputFileName &&
      bazelOpts.transpiledJsOutputDirectory) {
    throw new Error(
        'In JS transpilation mode, cannot set both ' +
        'transpiledJsOutputFileName and transpiledJsOutputDirectory.');
  }
}

const SOURCE_EXT = /((\.d)?\.tsx?|\.js)$/;

/**
 * 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;
  moduleResolutionHost: ts.ModuleResolutionHost = this;
  // TODO(evanm): delete this once tsickle is updated.
  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(SOURCE_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(SOURCE_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);
      // check that the fileName was actually underneath the package directory
      if (!relativeFileName.startsWith('..')) {
        if (this.bazelOpts.moduleRoot) {
          const root = this.bazelOpts.moduleRoot.replace(SOURCE_EXT, '');
          if (root === relativeFileName ||
              path.posix.join(root, 'index') === 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);
      }
    }

    if (fileName.startsWith('node_modules/')) {
      return fileName.substring('node_modules/'.length);
    }

    // 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[] {
    if (!this.allowActionInputReads) return [];
    const result: ts.ResolvedTypeReferenceDirective[] = [];
    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 (!resolved) {
        if (DEBUG) {
          debug(`Failed to resolve type reference directive '${name}'`);
        }
        return;
      }
      // In typescript 2.x the return type for this function
      // is `(ts.ResolvedTypeReferenceDirective | undefined)[]` thus we actually
      // do allow returning `undefined` in the array but the function is typed
      // `(ts.ResolvedTypeReferenceDirective)[]` to compile with both typescript
      // 2.x and 3.0/3.1 without error. Typescript 3.0/3.1 do handle the `undefined`
      // values in the array correctly despite the return signature.
      // It looks like the return type change was a mistake because
      // it was changed back to include `| undefined` recently:
      // https://github.com/Microsoft/TypeScript/pull/28059.
      result.push(resolved as ts.ResolvedTypeReferenceDirective);
    });
    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>|undefined): 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>|undefined): 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) {
      if (this.bazelOpts.transpiledJsOutputFileName) {
        fileName = this.bazelOpts.transpiledJsOutputFileName!;
      } else {
        // Strip the input directory path off of fileName to get the logical
        // path within the input directory.
        fileName =
            path.relative(this.bazelOpts.transpiledJsInputDirectory!, fileName);
        // Then prepend the output directory name.
        fileName =
            path.join(this.bazelOpts.transpiledJsOutputDirectory!, fileName);
      }
    } 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);
  }

  getDefaultLibLocation(): string {
    // 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.
    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 ? this.delegate.getDirectories(path) :
                                          [];
  }

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

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