text: // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.
  var common = require('./common.js');
  var classCategory = 'class';
  var namespaceCategory = 'ns';
  
  exports.transform = function (model) {
  
    if (!model) return null;
  
    langs = model.langs;
    handleItem(model, model._gitContribute, model._gitUrlPattern);
    if (model.children) {
      model.children.forEach(function (item) {
        handleItem(item, model._gitContribute, model._gitUrlPattern);
      });
    }
  
    if (model.type) {
      switch (model.type.toLowerCase()) {
        case 'namespace':
          model.isNamespace = true;
          if (model.children) groupChildren(model, namespaceCategory);
          break;
        case 'class':
        case 'interface':
        case 'struct':
        case 'delegate':
        case 'enum':
          model.isClass = true;
          if (model.children) groupChildren(model, classCategory);
          model[getTypePropertyName(model.type)] = true;
          break;
        default:
          break;
      }
    }
  
    return model;
  }
  
  exports.getBookmarks = function (model, ignoreChildren) {
    if (!model || !model.type || model.type.toLowerCase() === "namespace") return null;
  
    var bookmarks = {};
  
    if (typeof ignoreChildren == 'undefined' || ignoreChildren === false) {
      if (model.children) {
        model.children.forEach(function (item) {
          bookmarks[item.uid] = common.getHtmlId(item.uid);
          if (item.overload && item.overload.uid) {
            bookmarks[item.overload.uid] = common.getHtmlId(item.overload.uid);
          }
        });
      }
    }
  
    // Reference's first level bookmark should have no anchor
    bookmarks[model.uid] = "";
    return bookmarks;
  }
  
  exports.groupChildren = groupChildren;
  exports.getTypePropertyName = getTypePropertyName;
  exports.getCategory = getCategory;
  
  function groupChildren(model, category) {
    if (!model || !model.type) {
      return;
    }
    var typeChildrenItems = getDefinitions(category);
    var grouped = {};
  
    model.children.forEach(function (c) {
      if (c.isEii) {
        var type = "eii";
      } else {
        var type = c.type.toLowerCase();
      }
      if (!grouped.hasOwnProperty(type)) {
        grouped[type] = [];
      }
      // special handle for field
      if (type === "field" && c.syntax) {
        c.syntax.fieldValue = c.syntax.return;
        c.syntax.return = undefined;
      }
      // special handle for property
      if ((type === "property" || type === "attachedproperty") && c.syntax) {
        c.syntax.propertyValue = c.syntax.return;
        c.syntax.return = undefined;
      }
      // special handle for event
      if ((type === "event" || type === "attachedevent") && c.syntax) {
        c.syntax.eventType = c.syntax.return;
        c.syntax.return = undefined;
      }
      grouped[type].push(c);
    })
  
    var children = [];
    for (var key in typeChildrenItems) {
      if (typeChildrenItems.hasOwnProperty(key) && grouped.hasOwnProperty(key)) {
        var typeChildrenItem = typeChildrenItems[key];
        var items = grouped[key];
        if (items && items.length > 0) {
          var item = {};
          for (var itemKey in typeChildrenItem) {
            if (typeChildrenItem.hasOwnProperty(itemKey)) {
              item[itemKey] = typeChildrenItem[itemKey];
            }
          }
          item.children = items;
          children.push(item);
        }
      }
    }
  
    model.children = children;
  }
  
  function getTypePropertyName(type) {
    if (!type) {
      return undefined;
    }
    var loweredType = type.toLowerCase();
    var definition = getDefinition(loweredType);
    if (definition) {
      return definition.typePropertyName;
    }
  
    return undefined;
  }
  
  function getCategory(type) {
    var classItems = getDefinitions(classCategory);
    if (classItems.hasOwnProperty(type)) {
      return classCategory;
    }
  
    var namespaceItems = getDefinitions(namespaceCategory);
    if (namespaceItems.hasOwnProperty(type)) {
      return namespaceCategory;
    }
    return undefined;
  }
  
  function getDefinition(type) {
    var classItems = getDefinitions(classCategory);
    if (classItems.hasOwnProperty(type)) {
      return classItems[type];
    }
    var namespaceItems = getDefinitions(namespaceCategory);
    if (namespaceItems.hasOwnProperty(type)) {
      return namespaceItems[type];
    }
    return undefined;
  }
  
  function getDefinitions(category) {
    var namespaceItems = {
      "class":        { inClass: true,        typePropertyName: "inClass",        id: "classes" },
      "struct":       { inStruct: true,       typePropertyName: "inStruct",       id: "structs" },
      "interface":    { inInterface: true,    typePropertyName: "inInterface",    id: "interfaces" },
      "enum":         { inEnum: true,         typePropertyName: "inEnum",         id: "enums" },
      "delegate":     { inDelegate: true,     typePropertyName: "inDelegate",     id: "delegates" }
    };
    var classItems = {
      "constructor":      { inConstructor: true,      typePropertyName: "inConstructor",      id: "constructors" },
      "field":            { inField: true,            typePropertyName: "inField",            id: "fields" },
      "property":         { inProperty: true,         typePropertyName: "inProperty",         id: "properties" },
      "attachedproperty": { inAttachedProperty: true, typePropertyName: "inAttachedProperty", id: "attachedProperties" },
      "method":           { inMethod: true,           typePropertyName: "inMethod",           id: "methods" },
      "event":            { inEvent: true,            typePropertyName: "inEvent",            id: "events" },
      "attachedevent":    { inAttachedEvent: true,    typePropertyName: "inAttachedEvent",    id: "attachedEvents" },
      "operator":         { inOperator: true,         typePropertyName: "inOperator",         id: "operators" },
      "eii":              { inEii: true,              typePropertyName: "inEii",              id: "eii" }
    };
    if (category === 'class') {
      return classItems;
    }
    if (category === 'ns') {
      return namespaceItems;
    }
    console.err("category '" + category + "' is not valid.");
    return undefined;
  }
  
  function handleItem(vm, gitContribute, gitUrlPattern) {
    // get contribution information
    vm.sourceurl = common.getViewSourceHref(vm, null, gitUrlPattern);
    vm.docurl = "https://github.com/microsoft/playwright-sharp/issues/new?title=Improve%20" + vm.name[0].value + "&body=Explain%20how%20would%20you%20like%20this%20document%20to%20be%20improved.%0ASource URL: " +
      vm.sourceurl.replace("#", "%23");
    
    // set to null incase mustache looks up
    vm.summary = vm.summary || null;
    vm.remarks = vm.remarks || null;
    vm.conceptual = vm.conceptual || null;
    vm.syntax = vm.syntax || null;
    vm.implements = vm.implements || null;
    vm.example = vm.example || null;
    common.processSeeAlso(vm);
  
    // id is used as default template's bookmark
    vm.id = common.getHtmlId(vm.uid);
    if (vm.overload && vm.overload.uid) {
      vm.overload.id = common.getHtmlId(vm.overload.uid);
    }
  
    if (vm.supported_platforms) {
      vm.supported_platforms = transformDictionaryToArray(vm.supported_platforms);
    }
  
    if (vm.requirements) {
      var type = vm.type.toLowerCase();
      if (type == "method") {
        vm.requirements_method = transformDictionaryToArray(vm.requirements);
      } else {
        vm.requirements = transformDictionaryToArray(vm.requirements);
      }
    }
  
    if (vm && langs) {
      if (shouldHideTitleType(vm)) {
        vm.hideTitleType = true;
      } else {
        vm.hideTitleType = false;
      }
  
      if (shouldHideSubtitle(vm)) {
        vm.hideSubtitle = true;
      } else {
        vm.hideSubtitle = false;
      }
    }
  
    function shouldHideTitleType(vm) {
      var type = vm.type.toLowerCase();
      return ((type === 'namespace' && langs.length == 1 && (langs[0] === 'objectivec' || langs[0] === 'java' || langs[0] === 'c'))
        || ((type === 'class' || type === 'enum') && langs.length == 1 && langs[0] === 'c'));
    }
  
    function shouldHideSubtitle(vm) {
      var type = vm.type.toLowerCase();
      return (type === 'class' || type === 'namespace') && langs.length == 1 && langs[0] === 'c';
    }
  
    function transformDictionaryToArray(dic) {
      var array = [];
      for (var key in dic) {
        if (dic.hasOwnProperty(key)) {
          array.push({ "name": key, "value": dic[key] })
        }
      }
  
      return array;
    }
  }