/*
 * 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.tuweni.config;

import static org.apache.tuweni.toml.Toml.joinKeyPath;
import static org.apache.tuweni.toml.Toml.parseDottedKey;

import org.apache.tuweni.toml.TomlArray;
import org.apache.tuweni.toml.TomlInvalidTypeException;
import org.apache.tuweni.toml.TomlParseResult;
import org.apache.tuweni.toml.TomlPosition;
import org.apache.tuweni.toml.TomlTable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;

final class TomlBackedConfiguration implements Configuration {

  private final TomlTable toml;
  private final Schema schema;
  private final List<ConfigurationError> errors;

  TomlBackedConfiguration(TomlParseResult toml, @Nullable Schema schema) {
    List<ConfigurationError> errors = new ArrayList<>();
    toml.errors().forEach(
        err -> errors.add(new ConfigurationError(documentPosition(err.position()), err.getMessage(), err)));
    if (schema != null) {
      schema.validate(new TomlBackedConfiguration(toml, null)).forEach(errors::add);
    } else {
      schema = Schema.EMPTY;
    }

    this.toml = toml;
    this.schema = schema;
    this.errors = errors;
  }

  @Override
  public List<ConfigurationError> errors() {
    return errors;
  }

  @Override
  public void toToml(Appendable appendable) throws IOException {
    new TomlSerializer(this, schema).writeTo(appendable);
  }

  @Override
  public Set<String> keySet() {
    Set<String> keys = new HashSet<>();
    keys.addAll(toml.dottedKeySet());
    keys.addAll(schema.defaultsKeySet());
    return keys;
  }

  @Override
  public boolean contains(String key) {
    return toml.contains(key) || schema.hasDefault(key);
  }

  @Nullable
  @Override
  public Object get(String key) {
    Object obj = toml.get(key);
    if (obj != null) {
      if (obj instanceof TomlArray) {
        return deepToList((TomlArray) obj);
      }
      if (obj instanceof TomlTable) {
        return deepToMap((TomlTable) obj);
      }
      return obj;
    }
    return schema.getDefault(key);
  }

  @Nullable
  @Override
  public DocumentPosition inputPositionOf(String key) {
    TomlPosition position = toml.inputPositionOf(key);
    if (position == null) {
      return null;
    }
    return documentPosition(position);
  }

  private DocumentPosition inputPositionOf(List<String> keyPath) {
    TomlPosition position = toml.inputPositionOf(keyPath);
    if (position == null) {
      return null;
    }
    return documentPosition(position);
  }

  @Override
  public String getString(String key) {
    return getValue(key, toml::getString, schema::getDefaultString);
  }

  @Override
  public int getInteger(String key) {
    return getValue(key, keyPath -> {
      Long longValue = toml.getLong(keyPath);
      if (longValue != null && longValue > Integer.MAX_VALUE) {
        throw new InvalidConfigurationPropertyTypeException(
            inputPositionOf(keyPath),
            "Value of property '" + joinKeyPath(keyPath) + "' is too large for an integer");
      }
      return (longValue != null) ? longValue.intValue() : null;
    }, schema::getDefaultInteger);
  }

  @Override
  public long getLong(String key) {
    return getValue(key, toml::getLong, schema::getDefaultLong);
  }

  @Override
  public double getDouble(String key) {
    return getValue(key, toml::getDouble, schema::getDefaultDouble);
  }

  @Override
  public boolean getBoolean(String key) {
    return getValue(key, toml::getBoolean, schema::getDefaultBoolean);
  }

  @Override
  public Map<String, Object> getMap(String key) {
    return getValue(key, keyPath -> {
      TomlTable table = toml.getTable(keyPath);
      if (table == null) {
        return null;
      }
      return deepToMap(table);
    }, schema::getDefaultMap);
  }

  @Override
  public List<Object> getList(String key) {
    return getValue(key, keyPath -> {
      TomlArray array = toml.getArray(keyPath);
      if (array == null) {
        return null;
      }
      return deepToList(array);
    }, schema::getDefaultList);
  }

  @Override
  public List<String> getListOfString(String key) {
    return getList(key, "strings", TomlArray::containsStrings, schema::getDefaultListOfString);
  }

  @Override
  public List<Integer> getListOfInteger(String key) {
    return getValue(key, keyPath -> {
      TomlArray array = toml.getArray(keyPath);
      if (array == null) {
        return null;
      }
      if (!array.containsLongs()) {
        throw new InvalidConfigurationPropertyTypeException(
            inputPositionOf(keyPath),
            "List property '" + joinKeyPath(keyPath) + "' does not contain integers");
      }
      @SuppressWarnings("unchecked")
      List<Long> longList = (List<Long>) (List) array.toList();
      return IntStream.range(0, longList.size()).mapToObj(i -> {
        Long value = longList.get(i);
        if (value > Integer.MAX_VALUE) {
          throw new InvalidConfigurationPropertyTypeException(
              inputPositionOf(keyPath),
              "Value of property '" + joinKeyPath(keyPath) + "', index " + i + ", is too large for an integer");
        }
        return value.intValue();
      }).collect(Collectors.toList());
    }, schema::getDefaultListOfInteger);
  }

  @Override
  public List<Long> getListOfLong(String key) {
    return getList(key, "longs", TomlArray::containsLongs, schema::getDefaultListOfLong);
  }

  @Override
  public List<Double> getListOfDouble(String key) {
    return getList(key, "doubles", TomlArray::containsDoubles, schema::getDefaultListOfDouble);
  }

  @Override
  public List<Boolean> getListOfBoolean(String key) {
    return getList(key, "booleans", TomlArray::containsBooleans, schema::getDefaultListOfBoolean);
  }

  @Override
  public List<Map<String, Object>> getListOfMap(String key) {
    return getValue(key, keyPath -> {
      TomlArray array = toml.getArray(keyPath);
      if (array == null) {
        return null;
      }
      if (!array.containsTables()) {
        throw new InvalidConfigurationPropertyTypeException(
            inputPositionOf(keyPath),
            "List property '" + joinKeyPath(keyPath) + "' does not contain maps");
      }
      @SuppressWarnings("unchecked")
      List<Map<String, Object>> typedList = (List<Map<String, Object>>) (List) deepToList(array);
      return typedList;
    }, schema::getDefaultListOfMap);
  }

  private DocumentPosition documentPosition(TomlPosition position) {
    return DocumentPosition.positionAt(position.line(), position.column());
  }

  private <T> T getValue(String key, Function<List<String>, T> tomlGet, Function<String, T> defaultGet) {
    List<String> keyPath = parseDottedKey(key);
    T value;
    try {
      value = tomlGet.apply(keyPath);
    } catch (TomlInvalidTypeException e) {
      throw new InvalidConfigurationPropertyTypeException(inputPositionOf(keyPath), e.getMessage(), e);
    }
    if (value != null) {
      return value;
    }
    String canonicalKey = joinKeyPath(keyPath);
    value = defaultGet.apply(canonicalKey);
    if (value != null) {
      return value;
    }
    throw new NoConfigurationPropertyException("No value for property '" + canonicalKey + "'");
  }

  private <T> List<T> getList(
      String key,
      String typeName,
      Predicate<TomlArray> tomlCheck,
      Function<String, List<T>> defaultGet) {
    return getValue(key, keyPath -> {
      TomlArray array = toml.getArray(keyPath);
      if (array == null) {
        return null;
      }
      if (!tomlCheck.test(array)) {
        throw new InvalidConfigurationPropertyTypeException(
            inputPositionOf(keyPath),
            "List property '" + joinKeyPath(keyPath) + "' does not contain " + typeName);
      }
      @SuppressWarnings("unchecked")
      List<T> typedList = (List<T>) array.toList();
      return typedList;
    }, defaultGet);
  }

  private static List<Object> deepToList(TomlArray array) {
    return array.toList().stream().map(o -> {
      if (o instanceof TomlArray) {
        return deepToList((TomlArray) o);
      }
      if (o instanceof TomlTable) {
        return deepToMap((TomlTable) o);
      }
      return o;
    }).collect(Collectors.toList());
  }

  private static Map<String, Object> deepToMap(TomlTable table) {
    return table.toMap().entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> {
      Object o = e.getValue();
      if (o instanceof TomlArray) {
        return deepToList((TomlArray) o);
      }
      if (o instanceof TomlTable) {
        return deepToMap((TomlTable) o);
      }
      return o;
    }));
  }
}
