/*
 * 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.hadoop.ozone.container.common.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.io.IOUtils;
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos
    .ContainerType;
import org.apache.hadoop.hdds.scm.container.common.helpers
    .StorageContainerException;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData;

import com.google.common.base.Preconditions;
import static org.apache.hadoop.ozone.container.keyvalue
    .KeyValueContainerData.KEYVALUE_YAML_TAG;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.AbstractConstruct;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.introspector.PropertyUtils;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

/**
 * Class for creating and reading .container files.
 */

public final class ContainerDataYaml {

  private static final Logger LOG =
      LoggerFactory.getLogger(ContainerDataYaml.class);

  private ContainerDataYaml() {

  }

  /**
   * Creates a .container file in yaml format.
   *
   * @param containerFile
   * @param containerData
   * @throws IOException
   */
  public static void createContainerFile(ContainerType containerType,
      ContainerData containerData, File containerFile) throws IOException {
    Writer writer = null;
    FileOutputStream out = null;
    try {
      // Create Yaml for given container type
      Yaml yaml = getYamlForContainerType(containerType);
      // Compute Checksum and update ContainerData
      containerData.computeAndSetChecksum(yaml);

      // Write the ContainerData with checksum to Yaml file.
      out = new FileOutputStream(
          containerFile);
      writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
      yaml.dump(containerData, writer);
    } finally {
      try {
        if (writer != null) {
          writer.flush();
          // make sure the container metadata is synced to disk.
          out.getFD().sync();
          writer.close();
        }
      } catch (IOException ex) {
        LOG.warn("Error occurred during closing the writer. ContainerID: " +
            containerData.getContainerID());
      }
      IOUtils.closeQuietly(out);
    }
  }

  /**
   * Read the yaml file, and return containerData.
   *
   * @throws IOException
   */
  public static ContainerData readContainerFile(File containerFile)
      throws IOException {
    Preconditions.checkNotNull(containerFile, "containerFile cannot be null");
    try (FileInputStream inputFileStream = new FileInputStream(containerFile)) {
      return readContainer(inputFileStream);
    }

  }

  /**
   * Read the yaml file content, and return containerData.
   *
   * @throws IOException
   */
  public static ContainerData readContainer(byte[] containerFileContent)
      throws IOException {
    return readContainer(
        new ByteArrayInputStream(containerFileContent));
  }

  /**
   * Read the yaml content, and return containerData.
   *
   * @throws IOException
   */
  public static ContainerData readContainer(InputStream input)
      throws IOException {

    ContainerData containerData;
    PropertyUtils propertyUtils = new PropertyUtils();
    propertyUtils.setBeanAccess(BeanAccess.FIELD);
    propertyUtils.setAllowReadOnlyProperties(true);

    Representer representer = new ContainerDataRepresenter();
    representer.setPropertyUtils(propertyUtils);

    Constructor containerDataConstructor = new ContainerDataConstructor();

    Yaml yaml = new Yaml(containerDataConstructor, representer);
    yaml.setBeanAccess(BeanAccess.FIELD);

    containerData = (ContainerData)
        yaml.load(input);

    return containerData;
  }

  /**
   * Given a ContainerType this method returns a Yaml representation of
   * the container properties.
   *
   * @param containerType type of container
   * @return Yamal representation of container properties
   *
   * @throws StorageContainerException if the type is unrecognized
   */
  public static Yaml getYamlForContainerType(ContainerType containerType)
      throws StorageContainerException {
    PropertyUtils propertyUtils = new PropertyUtils();
    propertyUtils.setBeanAccess(BeanAccess.FIELD);
    propertyUtils.setAllowReadOnlyProperties(true);

    switch (containerType) {
    case KeyValueContainer:
      Representer representer = new ContainerDataRepresenter();
      representer.setPropertyUtils(propertyUtils);
      representer.addClassTag(
          KeyValueContainerData.class,
          KeyValueContainerData.KEYVALUE_YAML_TAG);

      Constructor keyValueDataConstructor = new ContainerDataConstructor();

      return new Yaml(keyValueDataConstructor, representer);
    default:
      throw new StorageContainerException("Unrecognized container Type " +
          "format " + containerType, ContainerProtos.Result
          .UNKNOWN_CONTAINER_TYPE);
    }
  }

  /**
   * Representer class to define which fields need to be stored in yaml file.
   */
  private static class ContainerDataRepresenter extends Representer {
    @Override
    protected Set<Property> getProperties(Class<? extends Object> type) {
      Set<Property> set = super.getProperties(type);
      Set<Property> filtered = new TreeSet<Property>();

      // When a new Container type is added, we need to add what fields need
      // to be filtered here
      if (type.equals(KeyValueContainerData.class)) {
        List<String> yamlFields = KeyValueContainerData.getYamlFields();
        // filter properties
        for (Property prop : set) {
          String name = prop.getName();
          if (yamlFields.contains(name)) {
            filtered.add(prop);
          }
        }
      }
      return filtered;
    }

    /**
     * Omit properties with null value.
     */
    @Override
    protected NodeTuple representJavaBeanProperty(
        Object bean, Property property, Object value, Tag tag) {
      return value == null
          ? null
          : super.representJavaBeanProperty(bean, property, value, tag);
    }
  }

  /**
   * Constructor class for KeyValueData, which will be used by Yaml.
   */
  private static class ContainerDataConstructor extends Constructor {
    ContainerDataConstructor() {
      //Adding our own specific constructors for tags.
      // When a new Container type is added, we need to add yamlConstructor
      // for that
      this.yamlConstructors.put(
          KEYVALUE_YAML_TAG, new ConstructKeyValueContainerData());
      this.yamlConstructors.put(Tag.INT, new ConstructLong());
    }

    private class ConstructKeyValueContainerData extends AbstractConstruct {
      public Object construct(Node node) {
        MappingNode mnode = (MappingNode) node;
        Map<Object, Object> nodes = constructMapping(mnode);

        //Needed this, as TAG.INT type is by default converted to Long.
        long layOutVersion = (long) nodes.get(OzoneConsts.LAYOUTVERSION);
        ChunkLayOutVersion layoutVersion =
            ChunkLayOutVersion.getChunkLayOutVersion((int) layOutVersion);

        long size = (long) nodes.get(OzoneConsts.MAX_SIZE);

        String originPipelineId = (String) nodes.get(
            OzoneConsts.ORIGIN_PIPELINE_ID);
        String originNodeId = (String) nodes.get(OzoneConsts.ORIGIN_NODE_ID);

        //When a new field is added, it needs to be added here.
        KeyValueContainerData kvData = new KeyValueContainerData(
            (long) nodes.get(OzoneConsts.CONTAINER_ID), layoutVersion, size,
            originPipelineId, originNodeId);

        kvData.setContainerDBType((String)nodes.get(
            OzoneConsts.CONTAINER_DB_TYPE));
        kvData.setMetadataPath((String) nodes.get(
            OzoneConsts.METADATA_PATH));
        kvData.setChunksPath((String) nodes.get(OzoneConsts.CHUNKS_PATH));
        Map<String, String> meta = (Map) nodes.get(OzoneConsts.METADATA);
        kvData.setMetadata(meta);
        kvData.setChecksum((String) nodes.get(OzoneConsts.CHECKSUM));
        Long timestamp = (Long) nodes.get(OzoneConsts.DATA_SCAN_TIMESTAMP);
        kvData.setDataScanTimestamp(timestamp);
        String state = (String) nodes.get(OzoneConsts.STATE);
        kvData
            .setState(ContainerProtos.ContainerDataProto.State.valueOf(state));
        String schemaVersion = (String) nodes.get(OzoneConsts.SCHEMA_VERSION);
        kvData.setSchemaVersion(schemaVersion);

        return kvData;
      }
    }

    //Below code is taken from snake yaml, as snakeyaml tries to fit the
    // number if it fits in integer, otherwise returns long. So, slightly
    // modified the code to return long in all cases.
    private class ConstructLong extends AbstractConstruct {
      public Object construct(Node node) {
        String value = constructScalar((ScalarNode) node).toString()
            .replaceAll("_", "");
        int sign = +1;
        char first = value.charAt(0);
        if (first == '-') {
          sign = -1;
          value = value.substring(1);
        } else if (first == '+') {
          value = value.substring(1);
        }
        int base = 10;
        if ("0".equals(value)) {
          return Long.valueOf(0);
        } else if (value.startsWith("0b")) {
          value = value.substring(2);
          base = 2;
        } else if (value.startsWith("0x")) {
          value = value.substring(2);
          base = 16;
        } else if (value.startsWith("0")) {
          value = value.substring(1);
          base = 8;
        } else if (value.indexOf(':') != -1) {
          String[] digits = value.split(":");
          int bes = 1;
          int val = 0;
          for (int i = 0, j = digits.length; i < j; i++) {
            val += (Long.parseLong(digits[(j - i) - 1]) * bes);
            bes *= 60;
          }
          return createNumber(sign, String.valueOf(val), 10);
        } else {
          return createNumber(sign, value, 10);
        }
        return createNumber(sign, value, base);
      }
    }

    private Number createNumber(int sign, String number, int radix) {
      Number result;
      if (sign < 0) {
        number = "-" + number;
      }
      result = Long.valueOf(number, radix);
      return result;
    }
  }

}
