package com.github.duncpro.jackal.storage.properties;

import com.google.common.base.Preconditions;

import com.github.duncpro.jackal.storage.StorageException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class PropertiesFileStorage extends PropertiesStorage {
  private static final Logger log = LoggerFactory.getLogger(PropertiesFileStorage.class);

  private final File file;

  public PropertiesFileStorage(File file) throws StorageException {
    this(file, PropertiesStorage.DEFAULT_DELIM);
  }

  /**
   * Creates a PropertiesFileStorage.
   * 
   * @param file the file to use as storage
   * @param delim the delimiter used to separate parts in a path in the properties file
   * @throws StorageException an IOExcpetion occurred while reading the file
   */
  public PropertiesFileStorage(File file, String delim) throws StorageException {
    super(new BetterProperties(),
        Preconditions.checkNotNull(file, "File cannot be null.").getName(), delim);

    this.file = file;
    prepare();
  }

  @Override
  public void close() throws StorageException {
    log.debug("Writing file {}.", file.getPath());

    if (!file.exists()) {
      try {
        if (file.createNewFile()) {
          log.info("Generated new configuration file at {}!", file.getPath());
        } else {
          throw new StorageException("Cannot create " + file.getPath());
        }
      } catch (IOException ex) {
        throw new StorageException("Cannot create " + file.getPath(), ex);
      }
    }

    try (FileOutputStream fos = new FileOutputStream(file)) {
      properties.store(fos);
    } catch (IOException ex) {
      throw new StorageException("Cannot store " + file.getPath(), ex);
    }
  }

  private void prepare() throws StorageException {
    log.debug("Reading file: " + file.getPath() + ".");
    if (!file.exists()) {
      log.debug("... File not found.");
      // Nothing to load
      return;
    }

    try (FileInputStream fis = new FileInputStream(file)) {
      properties.load(fis);
    } catch (IOException ex) {
      throw new StorageException("Cannot read " + file.getPath(), ex);
    }
  }
}
