// 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.
 */
library from.html;

import 'dart:io';

import 'package:html5lib/dom.dart' as dom;
import 'package:html5lib/parser.dart' as parser;

import 'api.dart';
import 'html_tools.dart';

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'
];

/**
 * 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));
    }
  });
  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((String name, String 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 != null ? name : 'domain';
  checkAttributes(html, ['name'], context);
  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);
}

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);
  TypeDecl 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, 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 the file 'spec_input.html'.
 */
Api readApi() {
  File htmlFile = new File('spec_input.html');
  String htmlContents = htmlFile.readAsStringSync();
  dom.Document document = parser.parse(htmlContents);
  return apiFromHtml(document.firstChild);
}

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);
  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);
}

/**
 * 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);
  TypeDecl type = processContentsAsType(html, context);
  return new TypeDefinition(name, type, html);
}
/**
 * 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);
  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);
}

/**
 * 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']);
  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);
}

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

/**
 * 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);
  Map<String, TypeDefinition> types = <String, TypeDefinition>{};
  recurse(html, context, {
    'type': (dom.Element child) {
      TypeDefinition typeDefinition = typeDefinitionFromHtml(child);
      types[typeDefinition.name] = typeDefinition;
    }
  });
  return new Types(types, html);
}

typedef void ElementProcessor(dom.Element element);

typedef void TextProcessor(dom.Text text);
