// Copyright (c) 2017, 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/protocol/protocol_generated.dart' as server;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;

class ProtocolTestUtilities {
  static const List<String> strings = const <String>[
    'aa',
    'ab',
    'ac',
    'ad',
    'ae',
    'af',
    'ag',
    'ah',
    'ai',
    'aj',
    'ak',
    'al',
    'am',
    'an',
    'ao',
    'ap',
    'aq',
    'ar',
    'as',
    'at',
    'au',
    'av',
    'aw',
    'ax',
    'ay',
    'az',
    'ba',
    'bb',
    'bc',
    'bd',
    'be',
    'bf',
    'bg',
    'bh',
    'bi',
    'bj',
    'bk',
    'bl',
    'bm',
    'bn',
    'bo',
    'bp',
    'bq',
    'br',
    'bs',
    'bt',
    'bu',
    'bv',
    'bw',
    'bx',
    'by',
    'bz',
  ];

  /**
   * On return, increment [stringIndex] by 3 (or 4 if no [file] name is
   * provided) and [intIndex] by 4.
   */
  AnalysisError analysisError(int stringIndex, int intIndex, {String file}) {
    return new AnalysisError(
        AnalysisErrorSeverity.ERROR,
        AnalysisErrorType.COMPILE_TIME_ERROR,
        location(stringIndex, intIndex, file: file),
        strings[stringIndex++],
        strings[stringIndex++],
        correction: strings[stringIndex++],
        hasFix: true);
  }

  /**
   * On return, increment [stringIndex] by 5 and [intIndex] by 5.
   */
  Element element(int stringIndex, int intIndex, {ElementKind kind}) =>
      new Element(kind ?? ElementKind.CLASS, strings[stringIndex++], intIndex++,
          location: new Location(fileName(stringIndex++), intIndex++,
              intIndex++, intIndex++, intIndex++),
          parameters: strings[stringIndex++],
          returnType: strings[stringIndex++],
          typeParameters: strings[stringIndex++]);

  String fileName(int stringIndex) => '${strings[stringIndex]}.dart';

  FoldingRegion foldingRegion(int offset, int length) =>
      new FoldingRegion(FoldingKind.FILE_HEADER, offset, length);

  HighlightRegion highlightRegion(int offset, int length) =>
      new HighlightRegion(HighlightRegionType.FIELD, offset, length);

  /**
   * On return, increment [stringIndex] by 1 and [intIndex] by 4.
   */
  Location location(int stringIndex, int intIndex, {String file}) =>
      new Location(file ?? fileName(stringIndex), intIndex++, intIndex++,
          intIndex++, intIndex++);

  /**
   * On return, increment [stringIndex] by 5 and [intIndex] by 7.
   */
  Occurrences occurrences(int stringIndex, int intIndex) {
    Element referencedElement = element(stringIndex, intIndex);
    return new Occurrences(referencedElement, <int>[intIndex + 5, intIndex + 6],
        referencedElement.name.length);
  }

  /**
   * On return, increment [stringIndex] by 10 and [intIndex] by 14.
   */
  Outline outline(int stringIndex, int intIndex) => new Outline(
          element(stringIndex, intIndex),
          intIndex + 5,
          intIndex + 6,
          intIndex + 5,
          intIndex + 6,
          children: <Outline>[
            new Outline(
                element(stringIndex + 5, intIndex + 7,
                    kind: ElementKind.METHOD),
                intIndex + 12,
                intIndex + 13,
                intIndex + 12,
                intIndex + 13)
          ]);

  /**
   * On return, increment [stringIndex] by 2 (or 3 if no [file] name is
   * provided) and [intIndex] by 4.
   */
  plugin.AnalysisNavigationParams pluginNavigationParams(
          int stringIndex, int intIndex, {String file}) =>
      new plugin.AnalysisNavigationParams(
          file ?? fileName(stringIndex++), <NavigationRegion>[
        new NavigationRegion(intIndex++, 2, <int>[0])
      ], <NavigationTarget>[
        new NavigationTarget(
            ElementKind.FIELD, 0, intIndex++, 2, intIndex++, intIndex++)
      ], <String>[
        strings[stringIndex++],
        strings[stringIndex++]
      ]);

  /**
   * On return, increment [stringIndex] by 2 and [intIndex] by 4.
   */
  RefactoringProblem refactoringProblem(int stringIndex, int intIndex) {
    return new RefactoringProblem(
        RefactoringProblemSeverity.FATAL, strings[stringIndex++],
        location: location(stringIndex, intIndex));
  }

  /**
   * On return, increment [stringIndex] by 2 (or 3 if no [file] name is
   * provided) and [intIndex] by 4.
   */
  server.AnalysisNavigationParams serverNavigationParams(
          int stringIndex, int intIndex, {String file}) =>
      new server.AnalysisNavigationParams(
          file ?? fileName(stringIndex++), <NavigationRegion>[
        new NavigationRegion(intIndex++, 2, <int>[0])
      ], <NavigationTarget>[
        new NavigationTarget(
            ElementKind.FIELD, 0, intIndex++, 2, intIndex++, intIndex++)
      ], <String>[
        strings[stringIndex++],
        strings[stringIndex++]
      ]);

  /**
   * On return, increment [stringIndex] by 6 and [intIndex] by 6.
   */
  SourceChange sourceChange(int stringIndex, int intIndex) =>
      new SourceChange(strings[stringIndex++],
          edits: <SourceFileEdit>[
            new SourceFileEdit(fileName(stringIndex), intIndex++,
                edits: <SourceEdit>[
                  new SourceEdit(intIndex++, intIndex++, strings[stringIndex++])
                ])
          ],
          linkedEditGroups: <LinkedEditGroup>[
            new LinkedEditGroup(
                <Position>[new Position(fileName(stringIndex), intIndex++)],
                intIndex++,
                <LinkedEditSuggestion>[
                  new LinkedEditSuggestion(
                      strings[stringIndex++], LinkedEditSuggestionKind.METHOD)
                ])
          ],
          selection: new Position(fileName(stringIndex), intIndex++));
}
