/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.internal.statistics;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;

import org.apache.geode.GemFireConfigException;
import org.apache.geode.StatisticDescriptor;
import org.apache.geode.StatisticsType;
import org.apache.geode.StatisticsTypeFactory;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.ClassPathLoader;

// @todo davidw Use a SAX parser instead of DOM
/**
 * This is an internal helper class for dealing with the SessionFactory XML configuration files.
 */
public class StatisticsTypeXml implements EntityResolver, ErrorHandler {

  /** The name of the DTD file */
  static final String DTD = "statisticsType.dtd";

  static final String systemId = "http://www.gemstone.com/dtd/" + DTD;
  static final String publicId = "-//GemStone Systems, Inc.//GemFire StatisticsType//EN";

  ///////////////////// Interface methods ///////////////////////

  /**
   * Given a publicId, attempts to resolve it to a DTD. Returns an <code>InputSource</code> for the
   * DTD.
   */
  @Override
  public InputSource resolveEntity(String publicId, String systemId) throws SAXException {

    // Figure out the location for the publicId. Be tolerant of other
    // versions of the dtd
    if (publicId.equals(StatisticsTypeXml.publicId) || systemId.equals(StatisticsTypeXml.systemId)
        || systemId.endsWith(DTD)) {

      // Public ID for system config DTD
      String location = "/org/apache/geode/" + DTD;
      InputStream stream = ClassPathLoader.getLatest().getResourceAsStream(getClass(), location);
      if (stream != null) {
        return new InputSource(stream);

      } else {
        throw new SAXNotRecognizedException(
            String.format("DTD not found: %s", location));
      }

    } else {
      throw new SAXNotRecognizedException(
          String.format("Invalid public ID: ' %s '", publicId));
    }
  }

  @Override
  public void warning(SAXParseException exception) throws SAXException {
    // We don't want to thrown an exception. We want to log it!!
    // FIXME
    // String s = "SAX warning while working with XML";
  }

  @Override
  public void error(SAXParseException exception) throws SAXException {
    throw new GemFireConfigException(
        "SAX error while working with XML",
        exception);
  }

  @Override
  public void fatalError(SAXParseException exception) throws SAXException {
    throw new GemFireConfigException(
        "SAX fatal error while working with XML",
        exception);
  }

  ////////////////////// Parsing XML File ////////////////////////

  /**
   * Parses the contents of XML data and from it creates one or more <code>StatisticsType</code>
   * instances.
   */
  public StatisticsType[] read(Reader reader, StatisticsTypeFactory statFactory) {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    // factory.setValidating(validate);

    DocumentBuilder parser = null;
    try {
      parser = factory.newDocumentBuilder();

    } catch (ParserConfigurationException ex) {
      throw new GemFireConfigException(
          "Failed parsing XML", ex);
    }

    parser.setErrorHandler(this);
    parser.setEntityResolver(this);
    Document doc;
    try {
      doc = parser.parse(new InputSource(reader));
    } catch (SAXException se) {
      throw new GemFireConfigException(
          "Failed parsing XML", se);
    } catch (IOException io) {
      throw new GemFireConfigException(
          "Failed reading XML data", io);
    }

    if (doc == null) {
      throw new GemFireConfigException(
          "Failed reading XML data; no document");
    }
    Element root = doc.getDocumentElement();
    if (root == null) {
      throw new GemFireConfigException(
          "Failed reading XML data; no root element");
    }
    return extractStatistics(root, statFactory);
  }

  /*
   * <!ELEMENT statistics (type)+>
   */
  private StatisticsType[] extractStatistics(Element root, StatisticsTypeFactory statFactory) {
    Assert.assertTrue(root.getTagName().equals("statistics"));

    ArrayList types = new ArrayList();
    NodeList typeNodes = root.getElementsByTagName("type");
    for (int i = 0; i < typeNodes.getLength(); i++) {
      Element typeNode = (Element) typeNodes.item(i);
      types.add(extractType(typeNode, statFactory));
    }
    return (StatisticsType[]) types.toArray(new StatisticsType[0]);
  }

  /**
   * <!ELEMENT type (description?, (stat)+)> <!ATTLIST type name CDATA #REQUIRED>
   */
  private StatisticsType extractType(Element typeNode, StatisticsTypeFactory statFactory) {
    Assert.assertTrue(typeNode.getTagName().equals("type"));
    Assert.assertTrue(typeNode.hasAttribute("name"));

    final String typeName = typeNode.getAttribute("name");
    ArrayList stats = new ArrayList();
    NodeList statNodes = typeNode.getElementsByTagName("stat");
    for (int i = 0; i < statNodes.getLength(); i++) {
      Element statNode = (Element) statNodes.item(i);
      stats.add(extractStat(statNode, statFactory));
    }
    StatisticDescriptor[] descriptors =
        (StatisticDescriptor[]) stats.toArray(new StatisticDescriptor[0]);
    String description = "";
    {
      NodeList descriptionNodes = typeNode.getElementsByTagName("description");
      if (descriptionNodes.getLength() > 0) {
        // descriptionNodes will contain the both our description, if it exists,
        // and any nested stat descriptions. Ours will always be first
        Element descriptionNode = (Element) descriptionNodes.item(0);
        // but make sure the first one belongs to our node
        if (descriptionNode.getParentNode().getNodeName().equals(typeNode.getNodeName())) {
          description = extractDescription(descriptionNode);
        }
      }
    }

    return statFactory.createType(typeName, description, descriptors);
  }

  private static final int INT_STORAGE = 0;
  private static final int LONG_STORAGE = 1;
  private static final int DOUBLE_STORAGE = 2;

  /**
   * <!ELEMENT stat (description?, unit?)> <!ATTLIST stat name CDATA #REQUIRED counter (true |
   * false) #IMPLIED largerBetter (true | false) #IMPLIED storage (int | long | double) #IMPLIED >
   */
  private StatisticDescriptor extractStat(Element statNode, StatisticsTypeFactory statFactory) {
    Assert.assertTrue(statNode.getTagName().equals("stat"));
    Assert.assertTrue(statNode.hasAttribute("name"));

    final String statName = statNode.getAttribute("name");
    String description = "";
    String unit = "";
    boolean isCounter = true;
    boolean largerBetter;
    int storage = INT_STORAGE;

    if (statNode.hasAttribute("counter")) {
      String value = statNode.getAttribute("counter");
      Assert.assertTrue(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"));
      isCounter = Boolean.valueOf(value).booleanValue();
    }
    largerBetter = isCounter; // default
    if (statNode.hasAttribute("largerBetter")) {
      String value = statNode.getAttribute("largerBetter");
      Assert.assertTrue(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"));
      largerBetter = Boolean.valueOf(value).booleanValue();
    }
    if (statNode.hasAttribute("storage")) {
      String value = statNode.getAttribute("storage");
      if (value.equalsIgnoreCase("int")) {
        storage = INT_STORAGE;
      } else if (value.equalsIgnoreCase("long")) {
        storage = LONG_STORAGE;
      } else {
        Assert.assertTrue(value.equalsIgnoreCase("double"));
        storage = DOUBLE_STORAGE;
      }
    }
    {
      NodeList descriptionNodes = statNode.getElementsByTagName("description");
      Assert.assertTrue(descriptionNodes.getLength() <= 1);
      if (descriptionNodes.getLength() == 1) {
        Element descriptionNode = (Element) descriptionNodes.item(0);
        description = extractDescription(descriptionNode);
      }
    }

    {
      NodeList unitNodes = statNode.getElementsByTagName("unit");
      Assert.assertTrue(unitNodes.getLength() <= 1);
      if (unitNodes.getLength() == 1) {
        Element unitNode = (Element) unitNodes.item(0);
        unit = extractUnit(unitNode);
      }
    }
    if (isCounter) {
      switch (storage) {
        case INT_STORAGE:
          return statFactory.createIntCounter(statName, description, unit, largerBetter);
        case LONG_STORAGE:
          return statFactory.createLongCounter(statName, description, unit, largerBetter);
        case DOUBLE_STORAGE:
          return statFactory.createDoubleCounter(statName, description, unit, largerBetter);
        default:
          throw new RuntimeException(String.format("unexpected storage type %s",
              Integer.valueOf(storage)));
      }
    } else {
      switch (storage) {
        case INT_STORAGE:
          return statFactory.createIntGauge(statName, description, unit, largerBetter);
        case LONG_STORAGE:
          return statFactory.createLongGauge(statName, description, unit, largerBetter);
        case DOUBLE_STORAGE:
          return statFactory.createDoubleGauge(statName, description, unit, largerBetter);
        default:
          throw new RuntimeException(String.format("unexpected storage type %s",
              Integer.valueOf(storage)));
      }
    }
  }

  /**
   * <!ELEMENT description (#PCDATA)>
   */
  private String extractDescription(Element descriptionNode) {
    Assert.assertTrue(descriptionNode.getTagName().equals("description"));
    return extractText(descriptionNode);
  }

  /**
   * <!ELEMENT unit (#PCDATA)>
   */
  private String extractUnit(Element unitNode) {
    Assert.assertTrue(unitNode.getTagName().equals("unit"));
    return extractText(unitNode);
  }

  private String extractText(Element element) {
    Text text = (Text) element.getFirstChild();
    return ((text == null ? "" : text.getData()));
  }
}
