// 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', 'plugin_spec.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 as String);
    });
    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);
    TypeObject params;
    recurse(html, context, {
      'params': (dom.Element child) {
        params = typeObjectFromHtml(child, '$context.params');
      }
    });
    return new Notification(domainName, event, params, html);
  }

  /**
   * 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 as TypeReference, 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);
    TypeObject feedback;
    TypeObject 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';
    TypeObject params;
    TypeObject 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;
  }
}
