import * as ts from 'typescript';
import {Fix, IndividualChange} from '../failure';
import {debugLog} from './ast_tools';

/**
 * A Fixer turns Nodes (that are supposed to have been matched before) into a
 * Fix. This is meant to be implemented by Rule implementers (or
 * ban-preset-pattern users). See also `buildReplacementFixer` for a simpler way
 * of implementing a Fixer.
 */
export interface Fixer {
  getFixForFlaggedNode(node: ts.Node): Fix|undefined;
}

/**
 * A simple Fixer builder based on a function that looks at a node, and
 * output either nothing, or a replacement. If this is too limiting, implement
 * Fixer instead.
 */
export function buildReplacementFixer(
    potentialReplacementGenerator: (node: ts.Node) =>
        ({replaceWith: string} | undefined)): Fixer {
  return {
    getFixForFlaggedNode: (n: ts.Node): Fix | undefined => {
      const partialFix = potentialReplacementGenerator(n);
      if (!partialFix) {
        return;
      }
      return {
        changes: [{
          sourceFile: n.getSourceFile(),
          start: n.getStart(),
          end: n.getEnd(),
          replacement: partialFix.replaceWith,
        }],
      };
    }
  };
}

// TODO(rjamet): Both maybeAddNamedImport and maybeAddNamespacedImport are too
// hard to read to my taste. This could probably be improved upon by being more
// functionnal, to show the filter passes and get rid of the continues and
// returns (which are confusing).

/**
 * Builds an IndividualChange that imports the required symbol from the given
 * file under the given name. This might reimport the same thing twice in some
 * cases, but it will always make it available under the right name (though
 * its name might collide with other imports, as we don't currently check for
 * that).
 */
export function maybeAddNamedImport(
    source: ts.SourceFile, importWhat: string, fromFile: string,
    importAs?: string, tazeComment?: string): IndividualChange|undefined {
  const importStatements = source.statements.filter(ts.isImportDeclaration);
  const importSpecifier =
      importAs ? `${importWhat} as ${importAs}` : importWhat;

  for (const iDecl of importStatements) {
    const parsedDecl = maybeParseImportNode(iDecl);
    if (!parsedDecl || parsedDecl.fromFile !== fromFile) {
      // Not an import from the right file, or couldn't understand the import.
      continue;  // Jump to the next import.
    }
    if (ts.isNamespaceImport(parsedDecl.namedBindings)) {
      debugLog(`... but it's a wildcard import`);
      continue;  // Jump to the next import.
    }

    // Else, bindings is a NamedImports. We can now search whether the right
    // symbol is there under the right name.
    const foundRightImport = parsedDecl.namedBindings.elements.some(
        iSpec => iSpec.propertyName ?
            iSpec.name.getText() === importAs &&  // import {foo as bar}
                iSpec.propertyName.getText() === importWhat :
            iSpec.name.getText() === importWhat);  // import {foo}

    if (foundRightImport) {
      debugLog(`"${iDecl.getFullText()}" imports ${importWhat} as we want.`);
      return;  // Our request is already imported under the right name.
    }

    // Else, insert our symbol in the list of imports from that file.
    debugLog(`No named imports from that file, generating new fix`);
    return {
      start: parsedDecl.namedBindings.elements[0].getStart(),
      end: parsedDecl.namedBindings.elements[0].getStart(),
      sourceFile: source,
      replacement: `${importSpecifier}, `,
    };
  }

  // If we get here, we didn't find anything imported from the wanted file, so
  // we'll need the full import string. Add it after the last import,
  // and let clang-format handle the rest.
  const newImportStatement = `import {${importSpecifier}} from '${fromFile}';` +
      (tazeComment ? `  ${tazeComment}\n` : `\n`);
  const insertionPosition = importStatements.length ?
      importStatements[importStatements.length - 1].getEnd() + 1 :
      0;
  return {
    start: insertionPosition,
    end: insertionPosition,
    sourceFile: source,
    replacement: newImportStatement,
  };
}

/**
 * Builds an IndividualChange that imports the required namespace from the given
 * file under the given name. This might reimport the same thing twice in some
 * cases, but it will always make it available under the right name (though
 * its name might collide with other imports, as we don't currently check for
 * that).
 */
export function maybeAddNamespaceImport(
    source: ts.SourceFile, fromFile: string, importAs: string,
    tazeComment?: string): IndividualChange|undefined {
  const importStatements = source.statements.filter(ts.isImportDeclaration);

  const hasTheRightImport = importStatements.some(iDecl => {
    const parsedDecl = maybeParseImportNode(iDecl);
    if (!parsedDecl || parsedDecl.fromFile !== fromFile) {
      // Not an import from the right file, or couldn't understand the import.
      return false;
    }
    debugLog(`"${iDecl.getFullText()}" is an import from the right file`);

    if (ts.isNamedImports(parsedDecl.namedBindings)) {
      debugLog(`... but it's a named import`);
      return false;  // irrelevant to our namespace imports
    }
    // Else, bindings is a NamespaceImport.
    if (parsedDecl.namedBindings.name.getText() !== importAs) {
      debugLog(`... but not the right name, we need to reimport`);
      return false;
    }
    debugLog(`... and the right name, no need to reimport`);
    return true;
  });

  if (!hasTheRightImport) {
    const insertionPosition = importStatements.length ?
        importStatements[importStatements.length - 1].getEnd() + 1 :
        0;
    return {
      start: insertionPosition,
      end: insertionPosition,
      sourceFile: source,
      replacement: tazeComment ?
          `import * as ${importAs} from '${fromFile}';  ${tazeComment}\n` :
          `import * as ${importAs} from '${fromFile}';\n`,
    };
  }
  return;
}

/**
 * This tries to make sense of an ImportDeclaration, and returns the interesting
 * parts, undefined if the import declaration is valid but not understandable by
 * the checker.
 */
function maybeParseImportNode(iDecl: ts.ImportDeclaration): {
  namedBindings: ts.NamedImportBindings|ts.NamespaceImport,
  fromFile: string
}|undefined {
  if (!iDecl.importClause) {
    // something like import "./file";
    debugLog(`Ignoring import without imported symbol: ${iDecl.getFullText()}`);
    return;
  }
  if (iDecl.importClause.name || !iDecl.importClause.namedBindings) {
    // Seems to happen in defaults imports like import Foo from 'Bar'.
    // Not much we can do with that when trying to get a hold of some symbols,
    // so just ignore that line (worst case, we'll suggest another import
    // style).
    debugLog(`Ignoring import: ${iDecl.getFullText()}`);
    return;
  }
  if (!ts.isStringLiteral(iDecl.moduleSpecifier)) {
    debugLog(`Ignoring import whose module specifier is not literal`);
    return;
  }
  return {
    namedBindings: iDecl.importClause.namedBindings,
    fromFile: iDecl.moduleSpecifier.text
  };
}
