// Copyright (c) 2014, 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.

/**
 * Code for reading an HTML API description.
 */
import 'dart:io';

import 'package:analyzer/src/codegen/html.dart';
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as parser;
import 'package:path/path.dart';

import 'api.dart';

/**
 * Read the API description from the file 'plugin_spec.html'.  [pkgPath] is the
 * path to the current package.
 */
Api readApi(String pkgPath) {
  ApiReader reader =
      new ApiReader(join(pkgPath, 'tool', 'spec', 'spec_input.html'));
  return reader.readApi();
}

typedef void ElementProcessor(dom.Element element);

typedef void TextProcessor(dom.Text text);

class ApiReader {
  static const List<String> specialElements = const [
    'domain',
    'feedback',
    'object',
    'refactorings',
    'refactoring',
    'type',
    'types',
    'request',
    'notification',
    'params',
    'result',
    'field',
    'list',
    'map',
    'enum',
    'key',
    'value',
    'options',
    'ref',
    'code',
    'version',
    'union',
    'index',
    'include'
  ];

  /**
   * The absolute and normalized path to the file being read.
   */
  final String filePath;

  /**
   * Initialize a newly created API reader to read from the file with the given
   * [filePath].
   */
  ApiReader(this.filePath);

  /**
   * Create an [Api] object from an HTML representation such as:
   *
   * <html>
   *   ...
   *   <body>
   *     ... <version>1.0</version> ...
   *     <domain name="...">...</domain> <!-- zero or more -->
   *     <types>...</types>
   *     <refactorings>...</refactorings>
   *   </body>
   * </html>
   *
   * Child elements of <api> can occur in any order.
   */
  Api apiFromHtml(dom.Element html) {
    Api api;
    List<String> versions = <String>[];
    List<Domain> domains = <Domain>[];
    Types types = null;
    Refactorings refactorings = null;
    recurse(html, 'api', {
      'domain': (dom.Element element) {
        domains.add(domainFromHtml(element));
      },
      'refactorings': (dom.Element element) {
        refactorings = refactoringsFromHtml(element);
      },
      'types': (dom.Element element) {
        types = typesFromHtml(element);
      },
      'version': (dom.Element element) {
        versions.add(innerText(element));
      },
      'index': (dom.Element element) {
        /* Ignore; generated dynamically. */
      }
    });
    if (versions.length != 1) {
      throw new Exception('The API must contain exactly one <version> element');
    }
    api = new Api(versions[0], domains, types, refactorings, html);
    return api;
  }

  /**
   * Check that the given [element] has all of the attributes in
   * [requiredAttributes], possibly some of the attributes in
   * [optionalAttributes], and no others.
   */
  void checkAttributes(
      dom.Element element, List<String> requiredAttributes, String context,
      {List<String> optionalAttributes: const []}) {
    Set<String> attributesFound = new Set<String>();
    element.attributes.forEach((name, value) {
      if (!requiredAttributes.contains(name) &&
          !optionalAttributes.contains(name)) {
        throw new Exception(
            '$context: Unexpected attribute in ${element.localName}: $name');
      }
      attributesFound.add(name);
    });
    for (String expectedAttribute in requiredAttributes) {
      if (!attributesFound.contains(expectedAttribute)) {
        throw new Exception('$context: ${element
            .localName} must contain attribute $expectedAttribute');
      }
    }
  }

  /**
   * Check that the given [element] has the given [expectedName].
   */
  void checkName(dom.Element element, String expectedName, [String context]) {
    if (element.localName != expectedName) {
      if (context == null) {
        context = element.localName;
      }
      throw new Exception(
          '$context: Expected $expectedName, found ${element.localName}');
    }
  }

  /**
   * Create a [Domain] object from an HTML representation such as:
   *
   * <domain name="domainName">
   *   <request method="...">...</request> <!-- zero or more -->
   *   <notification event="...">...</notification> <!-- zero or more -->
   * </domain>
   *
   * Child elements can occur in any order.
   */
  Domain domainFromHtml(dom.Element html) {
    checkName(html, 'domain');
    String name = html.attributes['name'];
    String context = name ?? 'domain';
    bool experimental = html.attributes['experimental'] == 'true';
    checkAttributes(html, ['name'], context,
        optionalAttributes: ['experimental']);
    List<Request> requests = <Request>[];
    List<Notification> notifications = <Notification>[];
    recurse(html, context, {
      'request': (dom.Element child) {
        requests.add(requestFromHtml(child, context));
      },
      'notification': (dom.Element child) {
        notifications.add(notificationFromHtml(child, context));
      }
    });
    return new Domain(name, requests, notifications, html,
        experimental: experimental);
  }

  dom.Element getAncestor(dom.Element html, String name, String context) {
    dom.Element ancestor = html.parent;
    while (ancestor != null) {
      if (ancestor.localName == name) {
        return ancestor;
      }
      ancestor = ancestor.parent;
    }
    throw new Exception(
        '$context: <${html.localName}> must be nested within <$name>');
  }

  /**
   * Create a [Notification] object from an HTML representation such as:
   *
   * <notification event="methodName">
   *   <params>...</params> <!-- optional -->
   * </notification>
   *
   * Note that the event name should not include the domain name.
   *
   * <params> has the same form as <object>, as described in [typeDeclFromHtml].
   *
   * Child elements can occur in any order.
   */
  Notification notificationFromHtml(dom.Element html, String context) {
    String domainName = getAncestor(html, 'domain', context).attributes['name'];
    checkName(html, 'notification', context);
    String event = html.attributes['event'];
    context = '$context.${event != null ? event : 'event'}';
    checkAttributes(html, ['event'], context,
        optionalAttributes: ['experimental']);
    bool experimental = html.attributes['experimental'] == 'true';
    TypeDecl params;
    recurse(html, context, {
      'params': (dom.Element child) {
        params = typeObjectFromHtml(child, '$context.params');
      }
    });
    return new Notification(domainName, event, params, html,
        experimental: experimental);
  }

  /**
   * Create a single of [TypeDecl] corresponding to the type defined inside the
   * given HTML element.
   */
  TypeDecl processContentsAsType(dom.Element html, String context) {
    List<TypeDecl> types = processContentsAsTypes(html, context);
    if (types.length != 1) {
      throw new Exception('$context: Exactly one type must be specified');
    }
    return types[0];
  }

  /**
   * Create a list of [TypeDecl]s corresponding to the types defined inside the
   * given HTML element.  The following forms are supported.
   *
   * To refer to a type declared elsewhere (or a built-in type):
   *
   *   <ref>typeName</ref>
   *
   * For a list: <list>ItemType</list>
   *
   * For a map: <map><key>KeyType</key><value>ValueType</value></map>
   *
   * For a JSON object:
   *
   *   <object>
   *     <field name="...">...</field> <!-- zero or more -->
   *   </object>
   *
   * For an enum:
   *
   *   <enum>
   *     <value>...</value> <!-- zero or more -->
   *   </enum>
   *
   * For a union type:
   *   <union>
   *     TYPE <!-- zero or more -->
   *   </union>
   */
  List<TypeDecl> processContentsAsTypes(dom.Element html, String context) {
    List<TypeDecl> types = <TypeDecl>[];
    recurse(html, context, {
      'object': (dom.Element child) {
        types.add(typeObjectFromHtml(child, context));
      },
      'list': (dom.Element child) {
        checkAttributes(child, [], context);
        types.add(new TypeList(processContentsAsType(child, context), child));
      },
      'map': (dom.Element child) {
        checkAttributes(child, [], context);
        TypeDecl keyType;
        TypeDecl valueType;
        recurse(child, context, {
          'key': (dom.Element child) {
            if (keyType != null) {
              throw new Exception('$context: Key type already specified');
            }
            keyType = processContentsAsType(child, '$context.key');
          },
          'value': (dom.Element child) {
            if (valueType != null) {
              throw new Exception('$context: Value type already specified');
            }
            valueType = processContentsAsType(child, '$context.value');
          }
        });
        if (keyType == null) {
          throw new Exception('$context: Key type not specified');
        }
        if (valueType == null) {
          throw new Exception('$context: Value type not specified');
        }
        types.add(new TypeMap(keyType, valueType, child));
      },
      'enum': (dom.Element child) {
        types.add(typeEnumFromHtml(child, context));
      },
      'ref': (dom.Element child) {
        checkAttributes(child, [], context);
        types.add(new TypeReference(innerText(child), child));
      },
      'union': (dom.Element child) {
        checkAttributes(child, ['field'], context);
        String field = child.attributes['field'];
        types.add(new TypeUnion(
            processContentsAsTypes(child, context), field, child));
      }
    });
    return types;
  }

  /**
   * Read the API description from file with the given [filePath].
   */
  Api readApi() {
    String htmlContents = new File(filePath).readAsStringSync();
    dom.Document document = parser.parse(htmlContents);
    dom.Element htmlElement = document.children
        .singleWhere((element) => element.localName.toLowerCase() == 'html');
    return apiFromHtml(htmlElement);
  }

  void recurse(dom.Element parent, String context,
      Map<String, ElementProcessor> elementProcessors) {
    for (String key in elementProcessors.keys) {
      if (!specialElements.contains(key)) {
        throw new Exception('$context: $key is not a special element');
      }
    }
    for (dom.Node node in parent.nodes) {
      if (node is dom.Element) {
        if (elementProcessors.containsKey(node.localName)) {
          elementProcessors[node.localName](node);
        } else if (specialElements.contains(node.localName)) {
          throw new Exception(
              '$context: Unexpected use of <${node.localName}>');
        } else {
          recurse(node, context, elementProcessors);
        }
      }
    }
  }

  /**
   * Create a [Refactoring] object from an HTML representation such as:
   *
   * <refactoring kind="refactoringKind">
   *   <feedback>...</feedback> <!-- optional -->
   *   <options>...</options> <!-- optional -->
   * </refactoring>
   *
   * <feedback> and <options> have the same form as <object>, as described in
   * [typeDeclFromHtml].
   *
   * Child elements can occur in any order.
   */
  Refactoring refactoringFromHtml(dom.Element html) {
    checkName(html, 'refactoring');
    String kind = html.attributes['kind'];
    String context = kind != null ? kind : 'refactoring';
    checkAttributes(html, ['kind'], context);
    TypeDecl feedback;
    TypeDecl options;
    recurse(html, context, {
      'feedback': (dom.Element child) {
        feedback = typeObjectFromHtml(child, '$context.feedback');
      },
      'options': (dom.Element child) {
        options = typeObjectFromHtml(child, '$context.options');
      }
    });
    return new Refactoring(kind, feedback, options, html);
  }

  /**
   * Create a [Refactorings] object from an HTML representation such as:
   *
   * <refactorings>
   *   <refactoring kind="...">...</refactoring> <!-- zero or more -->
   * </refactorings>
   */
  Refactorings refactoringsFromHtml(dom.Element html) {
    checkName(html, 'refactorings');
    String context = 'refactorings';
    checkAttributes(html, [], context);
    List<Refactoring> refactorings = <Refactoring>[];
    recurse(html, context, {
      'refactoring': (dom.Element child) {
        refactorings.add(refactoringFromHtml(child));
      }
    });
    return new Refactorings(refactorings, html);
  }

  /**
   * Create a [Request] object from an HTML representation such as:
   *
   * <request method="methodName">
   *   <params>...</params> <!-- optional -->
   *   <result>...</result> <!-- optional -->
   * </request>
   *
   * Note that the method name should not include the domain name.
   *
   * <params> and <result> have the same form as <object>, as described in
   * [typeDeclFromHtml].
   *
   * Child elements can occur in any order.
   */
  Request requestFromHtml(dom.Element html, String context) {
    String domainName = getAncestor(html, 'domain', context).attributes['name'];
    checkName(html, 'request', context);
    String method = html.attributes['method'];
    context = '$context.${method != null ? method : 'method'}';
    checkAttributes(html, ['method'], context,
        optionalAttributes: ['experimental', 'deprecated']);
    bool experimental = html.attributes['experimental'] == 'true';
    bool deprecated = html.attributes['deprecated'] == 'true';
    TypeDecl params;
    TypeDecl result;
    recurse(html, context, {
      'params': (dom.Element child) {
        params = typeObjectFromHtml(child, '$context.params');
      },
      'result': (dom.Element child) {
        result = typeObjectFromHtml(child, '$context.result');
      }
    });
    return new Request(domainName, method, params, result, html,
        experimental: experimental, deprecated: deprecated);
  }

  /**
   * Create a [TypeDefinition] object from an HTML representation such as:
   *
   * <type name="typeName">
   *   TYPE
   * </type>
   *
   * Where TYPE is any HTML that can be parsed by [typeDeclFromHtml].
   *
   * Child elements can occur in any order.
   */
  TypeDefinition typeDefinitionFromHtml(dom.Element html) {
    checkName(html, 'type');
    String name = html.attributes['name'];
    String context = name != null ? name : 'type';
    checkAttributes(html, ['name'], context,
        optionalAttributes: ['experimental', 'deprecated']);
    TypeDecl type = processContentsAsType(html, context);
    bool experimental = html.attributes['experimental'] == 'true';
    bool deprecated = html.attributes['deprecated'] == 'true';
    return new TypeDefinition(name, type, html,
        experimental: experimental, deprecated: deprecated);
  }

  /**
   * Create a [TypeEnum] from an HTML description.
   */
  TypeEnum typeEnumFromHtml(dom.Element html, String context) {
    checkName(html, 'enum', context);
    checkAttributes(html, [], context);
    List<TypeEnumValue> values = <TypeEnumValue>[];
    recurse(html, context, {
      'value': (dom.Element child) {
        values.add(typeEnumValueFromHtml(child, context));
      }
    });
    return new TypeEnum(values, html);
  }

  /**
   * Create a [TypeEnumValue] from an HTML description such as:
   *
   * <enum>
   *   <code>VALUE</code>
   * </enum>
   *
   * Where VALUE is the text of the enumerated value.
   *
   * Child elements can occur in any order.
   */
  TypeEnumValue typeEnumValueFromHtml(dom.Element html, String context) {
    checkName(html, 'value', context);
    checkAttributes(html, [], context, optionalAttributes: ['deprecated']);
    bool deprecated = html.attributes['deprecated'] == 'true';
    List<String> values = <String>[];
    recurse(html, context, {
      'code': (dom.Element child) {
        String text = innerText(child).trim();
        values.add(text);
      }
    });
    if (values.length != 1) {
      throw new Exception('$context: Exactly one value must be specified');
    }
    return new TypeEnumValue(values[0], html, deprecated: deprecated);
  }

  /**
   * Create a [TypeObjectField] from an HTML description such as:
   *
   * <field name="fieldName">
   *   TYPE
   * </field>
   *
   * Where TYPE is any HTML that can be parsed by [typeDeclFromHtml].
   *
   * In addition, the attribute optional="true" may be used to specify that the
   * field is optional, and the attribute value="..." may be used to specify that
   * the field is required to have a certain value.
   *
   * Child elements can occur in any order.
   */
  TypeObjectField typeObjectFieldFromHtml(dom.Element html, String context) {
    checkName(html, 'field', context);
    String name = html.attributes['name'];
    context = '$context.${name != null ? name : 'field'}';
    checkAttributes(html, ['name'], context,
        optionalAttributes: ['optional', 'value', 'deprecated']);
    bool deprecated = html.attributes['deprecated'] == 'true';
    bool optional = false;
    String optionalString = html.attributes['optional'];
    if (optionalString != null) {
      switch (optionalString) {
        case 'true':
          optional = true;
          break;
        case 'false':
          optional = false;
          break;
        default:
          throw new Exception(
              '$context: field contains invalid "optional" attribute: "$optionalString"');
      }
    }
    String value = html.attributes['value'];
    TypeDecl type = processContentsAsType(html, context);
    return new TypeObjectField(name, type, html,
        optional: optional, value: value, deprecated: deprecated);
  }

  /**
   * Create a [TypeObject] from an HTML description.
   */
  TypeObject typeObjectFromHtml(dom.Element html, String context) {
    checkAttributes(html, [], context, optionalAttributes: ['experimental']);
    List<TypeObjectField> fields = <TypeObjectField>[];
    recurse(html, context, {
      'field': (dom.Element child) {
        fields.add(typeObjectFieldFromHtml(child, context));
      }
    });
    bool experimental = html.attributes['experimental'] == 'true';
    return new TypeObject(fields, html, experimental: experimental);
  }

  /**
   * Create a [Types] object from an HTML representation such as:
   *
   * <types>
   *   <type name="...">...</type> <!-- zero or more -->
   * </types>
   */
  Types typesFromHtml(dom.Element html) {
    checkName(html, 'types');
    String context = 'types';
    checkAttributes(html, [], context);
    List<String> importUris = <String>[];
    Map<String, TypeDefinition> typeMap = <String, TypeDefinition>{};
    List<dom.Element> childElements = <dom.Element>[];
    recurse(html, context, {
      'include': (dom.Element child) {
        String importUri = child.attributes['import'];
        if (importUri != null) {
          importUris.add(importUri);
        }
        String relativePath = child.attributes['path'];
        String path = normalize(join(dirname(filePath), relativePath));
        ApiReader reader = new ApiReader(path);
        Api api = reader.readApi();
        for (TypeDefinition typeDefinition in api.types) {
          typeDefinition.isExternal = true;
          childElements.add(typeDefinition.html);
          typeMap[typeDefinition.name] = typeDefinition;
        }
      },
      'type': (dom.Element child) {
        TypeDefinition typeDefinition = typeDefinitionFromHtml(child);
        typeMap[typeDefinition.name] = typeDefinition;
      }
    });
    for (dom.Element element in childElements) {
      html.append(element);
    }
    Types types = new Types(typeMap, html);
    types.importUris.addAll(importUris);
    return types;
  }
}
