const xml2js = require("xml2js");
const fs = require("fs");

const blockDefinitions = {};
const predefinedValues = {};

module.exports.getPredefinedValues = () => {
  return predefinedValues;
};

module.exports.getDefinitionByName = (name) => {
  name = name.toLowerCase();
  for(let type in blockDefinitions) {
    for(let blockName in blockDefinitions[type]) {
      if(blockName.toLowerCase() === name || (blockDefinitions[type][blockName].useNameAttributeAsTagName && blockDefinitions[type][blockName].type.toLowerCase() === name)) {
        return blockDefinitions[type][blockName];
      }
    }
  }
  return false;
};

module.exports.getBlockDefinitions = () => {
  return blockDefinitions;
};

module.exports.loadBlockDefinitions = (onLoaded) => {
  // TODO: Handle properly if it doesn't exists
  fs.readFile(basePath + '/block-definitions/' + config.blockDefinitionFile, 'utf-8', function(err, xml) {
    xml2js.parseString(xml, function(err, result) {

      // TODO: Handle properly if invalid format
      if (result.blockdefinitions) {
        for (let blockCategory in result.blockdefinitions) {
          if (blockCategory == "predefined_values") {
            for(let i = 0; i < result.blockdefinitions[blockCategory].length; ++i) {
              predefinedValues[result.blockdefinitions[blockCategory][i].$.id] = result.blockdefinitions[blockCategory][i].value;
            }
          } else {
            blockDefinitions[blockCategory] = {};
            // [0] is there because there can only be one blockType
            for(let blockType in result.blockdefinitions[blockCategory][0]) {
              for(let j = 0; j < result.blockdefinitions[blockCategory][0][blockType].length; ++j) {
                let xmlBlock = result.blockdefinitions[blockCategory][0][blockType][j];

                let blockName = xmlBlock["$"].name;
                let displayName = xmlBlock["$"].displayName;
                let useNameAttributeAsTagName = xmlBlock["$"].useNameAttributeAsTagName === undefined ? false : true;
                let preventInteraction = xmlBlock["$"].preventInteraction === undefined ? false : true;
                let hidden = xmlBlock["$"].hidden === undefined ? false : true;
                let blockPropertiesGroupedByType = {};

                for(let propertyType in xmlBlock) {
                  if(propertyType != "$") {
                    blockPropertiesGroupedByType[propertyType] = [];
                    // Append all properties by removing all the zork that is generated by xml2json
                    for(let i = 0; i < xmlBlock[propertyType].length; ++i) {
                      // This mainly removes the $ because it's just annoying
                      // i'm annoyed
                      // this is annoying and unreadable
                      blockPropertiesGroupedByType[propertyType].push(xmlBlock[propertyType][i]["$"]);
                    }
                  }
                }

                blockDefinitions[blockCategory][blockName] = {
                  name: blockName,
                  displayName: displayName,
                  hidden: hidden,
                  useNameAttributeAsTagName: useNameAttributeAsTagName,
                  blockPropertiesGroupedByType: blockPropertiesGroupedByType,
                  type: blockType,
                  preventInteraction: preventInteraction
                };
              }
            }
          }
        }
      }
    });
    onLoaded();
  });
};
