// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
import 'package:analysis_server/plugin/edit/assist/assist_dart.dart';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/linter_visitor.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    show SourceChange, SourceEdit, SourceFileEdit;
import 'package:analyzer/src/generated/source.dart';
import 'package:front_end/src/scanner/token.dart';
import 'package:source_span/src/span.dart';

class EditDartFix {
  final AnalysisServer server;
  final Request request;
  final fixFolders = <Folder>[];
  final fixFiles = <File>[];

  List<String> descriptionOfFixes;
  List<String> otherRecommendations;
  SourceChange sourceChange;

  EditDartFix(this.server, this.request);

  void addFix(String description, SourceChange change) {
    descriptionOfFixes.add(description);
    for (SourceFileEdit fileEdit in change.edits) {
      for (SourceEdit sourceEdit in fileEdit.edits) {
        sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
      }
    }
  }

  void addRecommendation(String recommendation) {
    otherRecommendations.add(recommendation);
  }

  Future<Response> compute() async {
    final params = new EditDartfixParams.fromRequest(request);

    // Validate each included file and directory.
    final resourceProvider = server.resourceProvider;
    final contextManager = server.contextManager;
    for (String path in params.included) {
      if (!server.isValidFilePath(path)) {
        return new Response.invalidFilePathFormat(request, path);
      }
      Resource res = resourceProvider.getResource(path);
      if (!res.exists ||
          !(contextManager.includedPaths.contains(path) ||
              contextManager.isInAnalysisRoot(path))) {
        return new Response.fileNotAnalyzed(request, path);
      }
      if (res is Folder) {
        fixFolders.add(res);
      } else {
        fixFiles.add(res);
      }
    }

    // Get the desired lints
    final LintRule preferMixin = Registry.ruleRegistry['prefer_mixin'];
    if (preferMixin == null) {
      return new Response.serverError(
          request, 'Missing prefer_mixin lint', null);
    }
    final preferMixinFix = new PreferMixinFix(this);
    preferMixin.reporter = preferMixinFix;

    // Setup
    final linters = <Linter>[
      preferMixin,
    ];
    final fixes = <LinterFix>[
      preferMixinFix,
    ];
    final visitors = <AstVisitor>[];
    final registry = new NodeLintRegistry(false);
    for (Linter linter in linters) {
      final visitor = linter.getVisitor();
      if (visitor != null) {
        visitors.add(visitor);
      }
      if (linter is NodeLintRule) {
        (linter as NodeLintRule).registerNodeProcessors(registry);
      }
    }
    final AstVisitor astVisitor = visitors.isNotEmpty
        ? new ExceptionHandlingDelegatingAstVisitor(
            visitors, ExceptionHandlingDelegatingAstVisitor.logException)
        : null;
    final AstVisitor linterVisitor = new LinterVisitor(
        registry, ExceptionHandlingDelegatingAstVisitor.logException);

    // TODO(danrubel): Determine if a lint is configured to run as part of
    // standard analysis and use those results if available instead of
    // running the lint again.

    // Analyze each source file.
    final resources = <Resource>[];
    for (String rootPath in contextManager.includedPaths) {
      resources.add(resourceProvider.getResource(rootPath));
    }
    bool hasErrors = false;
    while (resources.isNotEmpty) {
      Resource res = resources.removeLast();
      if (res is Folder) {
        for (Resource child in res.getChildren()) {
          if (!child.shortName.startsWith('.') &&
              contextManager.isInAnalysisRoot(child.path)) {
            resources.add(child);
          }
        }
        continue;
      }
      AnalysisResult result = await server.getAnalysisResult(res.path);
      CompilationUnit unit = result?.unit;
      if (unit != null) {
        if (!hasErrors) {
          for (AnalysisError error in result.errors) {
            if (error.errorCode.type == ErrorType.SYNTACTIC_ERROR) {
              hasErrors = true;
              break;
            }
          }
        }
        Source source = result.sourceFactory.forUri2(result.uri);
        for (Linter linter in linters) {
          linter.reporter.source = source;
        }
        if (astVisitor != null) {
          unit.accept(astVisitor);
        }
        unit.accept(linterVisitor);
      }
    }

    // Cleanup
    for (Linter linter in linters) {
      linter.reporter = null;
    }

    // Reporting
    descriptionOfFixes = <String>[];
    otherRecommendations = <String>[];
    sourceChange = new SourceChange('dartfix');
    for (LinterFix fix in fixes) {
      await fix.applyFix();
    }
    return new EditDartfixResult(descriptionOfFixes, otherRecommendations,
            hasErrors, sourceChange.edits)
        .toResponse(request.id);
  }

  /// Return `true` if the path in within the set of `included` files
  /// or is within an `included` directory.
  bool isIncluded(String path) {
    if (path != null) {
      for (File file in fixFiles) {
        if (file.path == path) {
          return true;
        }
      }
      for (Folder folder in fixFolders) {
        if (folder.contains(path)) {
          return true;
        }
      }
    }
    return false;
  }
}

class EditDartFixAssistContext implements DartAssistContext {
  @override
  final AnalysisDriver analysisDriver;

  @override
  final int selectionLength;

  @override
  final int selectionOffset;

  @override
  final Source source;

  @override
  final CompilationUnit unit;

  EditDartFixAssistContext(
      EditDartFix dartFix, this.source, this.unit, AstNode node)
      : analysisDriver = dartFix.server.getAnalysisDriver(source.fullName),
        selectionOffset = node.offset,
        selectionLength = 0;
}

abstract class LinterFix implements ErrorReporter {
  final EditDartFix dartFix;

  @override
  Source source;

  LinterFix(this.dartFix);

  @override
  void reportError(AnalysisError error) {
    // ignored
  }

  @override
  void reportErrorForElement(ErrorCode errorCode, Element element,
      [List<Object> arguments]) {
    // ignored
  }

  @override
  void reportErrorForNode(ErrorCode errorCode, AstNode node,
      [List<Object> arguments]) {
    // ignored
  }

  @override
  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
      [List<Object> arguments]) {
    // ignored
  }

  @override
  void reportErrorForSpan(ErrorCode errorCode, SourceSpan span,
      [List<Object> arguments]) {
    // ignored
  }

  @override
  void reportErrorForToken(ErrorCode errorCode, Token token,
      [List<Object> arguments]) {
    // ignored
  }

  @override
  void reportTypeErrorForNode(
      ErrorCode errorCode, AstNode node, List<Object> arguments) {
    // ignored
  }

  void applyFix();
}

class PreferMixinFix extends LinterFix {
  final classesToConvert = new Set<Element>();

  PreferMixinFix(EditDartFix dartFix) : super(dartFix);

  @override
  void reportErrorForNode(ErrorCode errorCode, AstNode node,
      [List<Object> arguments]) {
    TypeName type = node;
    Element element = type.name.staticElement;
    String path = element.source?.fullName;
    if (path != null && dartFix.isIncluded(path)) {
      classesToConvert.add(element);
    }
  }

  @override
  void applyFix() async {
    for (Element elem in classesToConvert) {
      await convertClassToMixin(elem);
    }
  }

  void convertClassToMixin(Element elem) async {
    String path = elem.source?.fullName;
    AnalysisResult result = await dartFix.server.getAnalysisResult(path);

    // TODO(danrubel): Verify that class can be converted
    for (CompilationUnitMember declaration in result.unit.declarations) {
      if (declaration is ClassOrMixinDeclaration &&
          declaration.name.name == elem.name) {
        AssistProcessor processor = new AssistProcessor(
            new EditDartFixAssistContext(
                dartFix, elem.source, result.unit, declaration.name));
        List<Assist> assists = await processor
            .computeAssist(DartAssistKind.CONVERT_CLASS_TO_MIXIN);
        if (assists.isNotEmpty) {
          for (Assist assist in assists) {
            dartFix.addFix(
                'Convert class to mixin: ${elem.name}', assist.change);
          }
        } else {
          // TODO(danrubel): If assists is empty, then determine why
          // assist could not be performed and report that in the description.
          dartFix.addRecommendation(
              'Could not automatically convert ${elem.name} to a mixin'
              ' because the class contains a constructor.');
        }
      }
    }
  }
}
