// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(https://fxbug.dev/84961): Fix null safety and remove this language version.
// @dart=2.9

import 'dart:async';
import 'dart:io';

import 'package:doc_checker/errors.dart';
import 'package:doc_checker/link_verifier.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';

/// Verify yaml files.
/// _toc.yaml files are verified for fuchsia.dev hosting compliance,
/// while other yaml files are just checked for regular yaml syntax.
class YamlChecker {
  Set<String> _tocYamlSet;
  Set<String> _otherYamlSet;
  Set<String> _mdSet;
  String _rootYaml;
  String _rootDir;
  String _refDomain;

  // List of errors found.
  final List<Error> errors = <Error>[];
  final List<Link<String>> outOfTreeLinks = <Link<String>>[];

  static const List<String> validStatusValues = <String>[
    'alpha',
    'beta',
    'deprecated',
    'experimental',
    'external',
    'limited',
    'new'
  ];

  /// Creates a new instance of YamlChecker.
  ///
  /// [rootDir] is the parent directory of 'docs'. This is used
  ///           to locate the files on the filesystem.
  /// [rootYaml] is the fuchsia.dev compliant yaml file to start the
  ///            checking from.
  /// [yamls] is the list of .yaml files to check.
  /// [mdFiles] is the list of .md files to make sure they are
  ///           referenced in the yaml files.
  /// [refDomain] is the developer site domain where the reference documents
  ///             are published such as fuchsia.dev.
  YamlChecker(String rootDir, String rootYaml, List<String> yamls,
      List<String> mdFiles, String refDomain) {
    _rootYaml = rootYaml;
    _rootDir = rootDir;
    _refDomain = refDomain;

    if (rootYaml != null && !_isFuchsiaDevYaml(rootYaml)) {
      throw AssertionError(
          'If specified, root YAML file needs to be named "_toc.yaml": $rootYaml');
    }

    _tocYamlSet = <String>{}
      ..addAll(yamls.where(_isFuchsiaDevYaml))
      ..remove(_rootYaml);

    _otherYamlSet = <String>{}
      ..addAll(yamls.where((yaml) => !_isFuchsiaDevYaml(yaml)))
      ..remove(_rootYaml);

    _mdSet = <String>{}
      ..addAll(filterHidden(mdFiles))
      // Remove navbar.md since it is only used on fuchsia.googlesource.com.
      ..remove('$_rootDir/docs/navbar.md')
      // Remove docs/gen/build_arguments.md since it is generated, it is
      // accessed as a source file and not published.
      ..remove('$_rootDir/docs/gen/build_arguments.md');
  }

  static bool _isFuchsiaDevYaml(String filename) {
    return path.basename(filename) == '_toc.yaml';
  }

  /// Filters out paths that are hidden names according to
  /// https://developers.google.com/devsite/reference/filenames?hl=en#hidden_files_single_underscore.
  /// This function expects the input paths to already be canonicalized.
  List<String> filterHidden(List<String> mdFiles) {
    return mdFiles
        .where((doc) => !path
            .split(path.relative(doc, from: _rootDir))
            .any((component) => component.startsWith('_')))
        .toList();
  }

  /// Checks the validity of the yaml files.
  /// Returns true if no errors are found.
  /// Errors can be retrieved via the [errors]
  /// property.
  Future<bool> check() {
    var checks = <Future>[];

    if (_rootYaml != null) {
      File f = File(_rootYaml);
      checks.add(f.readAsString().then((String data) {
        parse(loadYamlDocuments(data), _rootYaml);
        for (String s in _tocYamlSet) {
          errors
              .add(Error(ErrorType.invalidMenu, null, 'unreferenced yaml $s'));
        }
        for (String s in _mdSet) {
          errors.add(Error(ErrorType.unreachablePage, null,
              'File $s not referenced in any yaml file'));
        }
      }));
    }
    for (String s in _otherYamlSet) {
      File f = File(s);
      checks.add(f.readAsString().then((String data) {
        try {
          loadYamlDocuments(data);
        } on YamlException catch (e) {
          errors.add(Error(ErrorType.unparseableYaml, null, '$s: $e'));
        }
      }));
    }

    return Future.wait(checks).then((value) => errors.isEmpty);
  }

  /// Parses the yaml structure.
  void parse(List<YamlDocument> doc, String filename) {
    for (YamlDocument d in doc) {
      validateTopLevel(d.contents.value, filename);
    }
  }

  /// Validates the top level of the menu.
  void validateTopLevel(YamlMap map, String filename) {
    for (String key in map.keys) {
      switch (key) {
        case 'guides':
        case 'samples':
        case 'support':
        case 'reference':
        case 'toc':
          {
            validateTocElement(map[key], filename);
          }
          break;
        default:
          {
            errors.add(Error(ErrorType.invalidMenu, filename,
                'Unknown top level key: $key'));
            break;
          }
      }
    }
  }

  /// Validates the toc element in the menu.
  void validateTocElement(YamlNode val, String filename) {
    // valid entries are documented at
    if (val is YamlList) {
      for (YamlNode node in val) {
        if (node.runtimeType == YamlMap) {
          validateContentMap(node, filename);
        } else {
          errors.add(Error(ErrorType.invalidMenu, filename,
              'Unexpected node of type: ${node.runtimeType} $node'));
        }
      }
    } else {
      errors.add(Error(ErrorType.invalidMenu, filename,
          'Expected a list, got ${val.runtimeType}: $val'));
    }
  }

  /// Validates the content of toc.
  void validateContentMap(YamlMap map, String filename) {
    for (String key in map.keys) {
      switch (key) {
        case 'alternate_paths':
          {
            validatePathList(map[key], filename);
          }
          break;
        case 'break':
        case 'skip_translation':
          {
            // only include if break : true.
            if (map[key] != true) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  '$key should only be included when set to true'));
            }
          }
          break;
        case 'section':
        case 'contents':
          {
            validateTocElement(map[key], filename);
          }
          break;
        case 'include':
          {
            processIncludedFile(map[key], filename);
          }
          break;
        case 'path':
          {
            String menuPath = map[key];
            if (validatePath(menuPath, filename)) {
              // If the path is to a file, check that the file exists.
              if (!menuPath.startsWith('https://') &&
                  !menuPath.startsWith('/reference/') &&
                  !menuPath.startsWith('//')) {
                checkFileExists(menuPath, filename);
              } else {
                Uri uri;
                try {
                  if (menuPath.startsWith('//')) {
                    uri = Uri.parse('https:$menuPath');
                  } else if (menuPath.startsWith('/reference')) {
                    uri = Uri.parse('$_refDomain$menuPath');
                  } else {
                    uri = Uri.parse(menuPath);
                  }
                } on FormatException {
                  errors.add(Error(ErrorType.invalidUri, filename, menuPath));
                  continue;
                }
                outOfTreeLinks.add(Link(uri, filename));
              }
            }
          }
          break;
        case 'path_attributes':
          {
            errors.add(Error(ErrorType.invalidMenu, filename,
                'path_attributes not supported on fuchsia.dev'));
          }
          break;
        case 'status':
          {
            if (!validStatusValues.contains(map[key])) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'invalid status value of ${map[key]}'));
            }
          }
          break;
        case 'step_group':
          {
            // make sure there is no section in this group.
            if (map.containsKey('section')) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'invalid use of \'step_group\'. Group cannot also contain \`section\`'));
            }
            if (!(map[key] is String)) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'invalid value of \'step_group\'. Expected String got ${map[key].runtimeType} ${map[key]}'));
            }
          }
          break;
        case 'style':
          {
            if (map.containsKey('break') || map.containsKey('include')) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'invalid use of \'style\'. Group cannot also contain `break` nor `include`'));
            }
            if (map[key] != 'accordion' && map[key] != 'divider') {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'invalid value of `style`. Expected `accordion` or `divider`'));
            }
            if (!map.containsKey('heading') && !map.containsKey('section')) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'invalid use of \'style\'. Group must also have `heading` or `section`.'));
            }
          }
          break;
        case 'heading':
        case 'name':
        case 'title':
          {
            if (map[key].runtimeType != String) {
              errors.add(Error(ErrorType.invalidMenu, filename,
                  'Expected String for $key, got ${map[key].runtimeType}'));
            }
          }
          break;
        default:
          errors.add(Error(
              ErrorType.invalidMenu, filename, 'Unknown Content Key $key'));
      }
    }
  }

  /// Handles an included yaml file. It is validated completely then returns.
  void processIncludedFile(String menuPath, String parentFilename) {
    if (validatePath(menuPath, parentFilename)) {
      String filePath = '$_rootDir$menuPath';

      // parse in a try/catch to handle any syntax errors reading the included file.
      try {
        parse(loadYamlDocuments(File(filePath).readAsStringSync()), menuPath);
        _tocYamlSet.remove(filePath);
      } on Exception catch (exception) {
        errors.add(
            Error(ErrorType.invalidMenu, parentFilename, exception.toString()));
      }
    }
  }

  /// Validates a list of paths are valid paths for the menu.
  bool validatePathList(List<String> paths, String filename) {
    for (String s in paths) {
      if (!validatePath(s, filename)) {
        return false;
      }
    }
    return true;
  }

  /// Validates the path is valid for the menu.
  ///
  /// Valid paths are /docs/*, /reference/*, and
  /// http URLs.  Exceptions are made for
  /// CONTRIBUTING.md and CODE_OF_CONDUCT.md which
  /// are in the root of the project.
  bool validatePath(String menuPath, String filename) {
    if (!menuPath.startsWith('/docs') &&
        !menuPath.startsWith('http://') &&
        !menuPath.startsWith('https://') &&
        !menuPath.startsWith('/reference') &&
        !menuPath.startsWith('//') &&
        menuPath != '/CONTRIBUTING.md' &&
        menuPath != '/CODE_OF_CONDUCT.md') {
      errors.add(Error(ErrorType.invalidMenu, filename,
          'Path needs to start with \'/docs\' or \'/reference\', got $menuPath'));
      return false;
    }

    return true;
  }

  /// Check that the file pointed to by the path exists.
  /// if it does, remove the file from the mdSet to keep track of
  /// which files are referenced.
  void checkFileExists(String menuPath, String filename) {
    String filePath = '$_rootDir$menuPath';

    if (File(filePath).existsSync()) {
      _mdSet.remove(filePath);
    } else {
      // could be a directory, so add README.md.
      filePath = '$filePath/README.md';
      if (File(filePath).existsSync()) {
        _mdSet.remove(filePath);
      } else {
        errors.add(Error(ErrorType.invalidMenu, filename,
            'Invalid menu path $menuPath not found'));
      }
    }
  }
}
