// 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:html/dom.dart' as dom;
import 'package:html/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',
  'index'
];

/**
 * 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((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);
  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);
  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);
