// Copyright 2014 The Flutter Authors. 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:html/dom.dart';
import 'package:html/parser.dart';

import 'base/common.dart';
import 'base/file_system.dart';

/// Placeholder for base href
const String kBaseHrefPlaceholder = r'$FLUTTER_BASE_HREF';

class WebTemplateWarning {
  WebTemplateWarning(
    this.warningText,
    this.lineNumber,
  );
  final String warningText;
  final int lineNumber;
}

/// Utility class for parsing and performing operations on the contents of the
/// index.html file.
///
/// For example, to parse the base href from the index.html file:
///
/// ```dart
/// String parseBaseHref(File indexHtmlFile) {
///   final IndexHtml indexHtml = IndexHtml(indexHtmlFile.readAsStringSync());
///   return indexHtml.getBaseHref();
/// }
/// ```
class WebTemplate {
  WebTemplate(this._content);

  String get content => _content;
  String _content;

  Document _getDocument() => parse(_content);

  /// Parses the base href from the index.html file.
  String getBaseHref() {
    final Element? baseElement = _getDocument().querySelector('base');
    final String? baseHref = baseElement?.attributes == null
        ? null
        : baseElement!.attributes['href'];

    if (baseHref == null || baseHref == kBaseHrefPlaceholder) {
      return '';
    }

    if (!baseHref.startsWith('/')) {
      throw ToolExit(
        'Error: The base href in "web/index.html" must be absolute (i.e. start '
        'with a "/"), but found: `${baseElement!.outerHtml}`.\n'
        '$_kBasePathExample',
      );
    }

    if (!baseHref.endsWith('/')) {
      throw ToolExit(
        'Error: The base href in "web/index.html" must end with a "/", but found: `${baseElement!.outerHtml}`.\n'
        '$_kBasePathExample',
      );
    }

    return stripLeadingSlash(stripTrailingSlash(baseHref));
  }

  List<WebTemplateWarning> getWarnings() {
    return <WebTemplateWarning>[
      ..._getWarningsForPattern(
        RegExp('(const|var) serviceWorkerVersion = null'),
        'Local variable for "serviceWorkerVersion" is deprecated. Use "{{flutter_service_worker_version}}" template token instead.',
      ),
      ..._getWarningsForPattern(
        "navigator.serviceWorker.register('flutter_service_worker.js')",
        'Manual service worker registration deprecated. Use flutter.js service worker bootstrapping instead.',
      ),
      ..._getWarningsForPattern(
        '_flutter.loader.loadEntrypoint(',
        '"FlutterLoader.loadEntrypoint" is deprecated. Use "FlutterLoader.load" instead.',
      ),
    ];
  }

  List<WebTemplateWarning> _getWarningsForPattern(Pattern pattern, String warningText) {
    return <WebTemplateWarning>[
      for (final Match match in pattern.allMatches(_content))
        _getWarningForMatch(match, warningText)
    ];
  }

  WebTemplateWarning _getWarningForMatch(Match match, String warningText) {
    final int lineCount = RegExp(r'(\r\n|\r|\n)').allMatches(_content.substring(0, match.start)).length;
    return WebTemplateWarning(warningText, lineCount + 1);
  }

  /// Applies substitutions to the content of the index.html file.
  void applySubstitutions({
    required String baseHref,
    required String? serviceWorkerVersion,
    required File flutterJsFile,
    String? buildConfig,
    String? flutterBootstrapJs,
  }) {
    if (_content.contains(kBaseHrefPlaceholder)) {
      _content = _content.replaceAll(kBaseHrefPlaceholder, baseHref);
    }

    if (serviceWorkerVersion != null) {
      _content = _content
          .replaceFirst(
            // Support older `var` syntax as well as new `const` syntax
            RegExp('(const|var) serviceWorkerVersion = null'),
            'const serviceWorkerVersion = "$serviceWorkerVersion"',
          )
          // This is for legacy index.html that still uses the old service
          // worker loading mechanism.
          .replaceFirst(
            "navigator.serviceWorker.register('flutter_service_worker.js')",
            "navigator.serviceWorker.register('flutter_service_worker.js?v=$serviceWorkerVersion')",
          );
    }
    _content = _content.replaceAll(
      '{{flutter_service_worker_version}}',
      serviceWorkerVersion != null ? '"$serviceWorkerVersion"' : 'null',
    );
    if (buildConfig != null) {
      _content = _content.replaceAll(
        '{{flutter_build_config}}',
        buildConfig,
      );
    }

    if (_content.contains('{{flutter_js}}')) {
      _content = _content.replaceAll(
        '{{flutter_js}}',
        flutterJsFile.readAsStringSync(),
      );
    }

    if (flutterBootstrapJs != null) {
      _content = _content.replaceAll(
        '{{flutter_bootstrap_js}}',
        flutterBootstrapJs,
      );
    }
  }
}

/// Strips the leading slash from a path.
String stripLeadingSlash(String path) {
  while (path.startsWith('/')) {
    path = path.substring(1);
  }
  return path;
}

/// Strips the trailing slash from a path.
String stripTrailingSlash(String path) {
  while (path.endsWith('/')) {
    path = path.substring(0, path.length - 1);
  }
  return path;
}

const String _kBasePathExample = '''
For example, to serve from the root use:

    <base href="/">

To serve from a subpath "foo" (i.e. http://localhost:8080/foo/ instead of http://localhost:8080/) use:

    <base href="/foo/">

For more information, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
''';
