/*
 * Copyright (c) 2017 Diona Ltd.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of Diona
 * ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you
 * entered into with Diona.
 */

package org.odk.collect.android.utilities;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;

/**
 * Manages the list of binary files used by default in forms and assessments.
 */
public class DefaultBinaryManager {

  private static final String FILE_NAME = "defaultBinaryFileNames";

  /**
   * Save the file names of the default images for an upload field.
   *
   * @param map
   *     the map containing key value pairs  of the field references and the file name of the default image associated
   *     with the field.
   * @param parentDir
   *     the parent directory in which the map shall be saved.
   */
  public static void save(final HashMap<String, String> map, final File parentDir) {
    final File file = new File(parentDir, FILE_NAME);
    if (file.exists()) {
      file.delete();
    }
    FileOutputStream fos = null;
    ObjectOutputStream out = null;
    try {
      fos = new FileOutputStream(file);
      out = new ObjectOutputStream(fos);
      out.writeObject(map);
    } catch (IOException ex) {
      throw new RuntimeException("Failed to save default binary.", ex);
    } finally {
      try {
        if (fos != null) {
          fos.flush();
          fos.close();
        }
        if (out != null) {
          out.flush();
          out.close();
        }
      } catch (Exception e) {
        // Can't close the files but we managed to write to them successfully so move on.
      }
    }
  }

  /**
   * Read the file names of the default images for an upload field.
   *
   * @param ref
   *     the reference for the field.
   * @param parentDir
   *     the parent directory in which the default names are stored.
   *
   * @return the file name for the default image for the field or null.
   */
  public static String getFileName(final String ref, final File parentDir) {
    final HashMap<String, String> map = listForDir(parentDir);
    return map == null ? null : map.get(ref);
  }

  /**
   * List all reference-file name combinations for a directory.
   *
   * @param directory
   *     the directory containing the files.
   *
   * @return a HashMap of reference-file name pairs.
   */
  public static HashMap<String, String> listForDir(final File directory) {
    HashMap<String, String> map = new HashMap<>();
    File fileName = new File(directory, FILE_NAME);
    if (!fileName.exists()) {
      return map;
    }

    FileInputStream fis = null;
    ObjectInputStream in = null;
    try {
      fis = new FileInputStream(fileName);
      in = new ObjectInputStream(fis);
      map = (HashMap<String, String>) in.readObject();

    } catch (IOException | ClassNotFoundException e) {
      throw new RuntimeException("Failed to read default file names.", e);
    } finally {

      try {
        if (fis != null) {
          fis.close();
        }
        if (in != null) {
          in.close();
        }
      } catch (IOException e) {
        // Can't close the files but we managed to write to them successfully so move on.
      }
    }
    return map;
  }
}
