package app.service;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import app.model.Model;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class FiletreeOperations {

  private static int iconSize = 20;

  private FiletreeOperations() {}

  // TODO: Clean up code that is not in use
  // TODO: Error check for recursiveness, and files without icons

  /**
   * The method to generate the fileTree recursively. If it is a directory a
   * CheckBoxStringItem is created and the method is called again. It goes through
   * all until every directory or file inside the orginal CheckBoxItem is made. If
   * the item is a file it sends it to the help function checkExtension which is
   * described below.
   */
  public static void generateTree(File file, CheckBoxTreeItem<String> parent) {

    Image folder = new Image(FiletreeOperations.class.getResourceAsStream("/graphics/folder.png"));

    if (file.isDirectory()) {
      ImageView icon = new ImageView(folder);
      icon.setFitHeight(iconSize);
      icon.setFitWidth(iconSize);

      CheckBoxTreeItem<String> element = new CheckBoxTreeItem<>(file.getName(), icon);
      parent.getChildren().add(element);

      List<File> dirList = new ArrayList<>();
      List<File> fileList = new ArrayList<>();

      sortFiles(dirList, fileList, file);

      for (File f : dirList) {
        generateTree(f, element);
      }

    } else {

      try {
        ImageView icon = new ImageView(getIconForFile(file));
        icon.setFitHeight(iconSize);
        icon.setFitWidth(iconSize);

        CheckBoxTreeItem<String> element = new CheckBoxTreeItem<>(file.getName(), icon);
        parent.getChildren().add(element);

      } catch (Exception e) {
        System.err.println("[ERROR] Default file icon not found");
        System.err.println(e);
      }
    }
  }

  /**
   * A helping function to sort the files/directories in the fileTree so that it shows
   * in the correct order.
   */
  private static void sortFiles(List<File> dirList, List<File> fileList, File file) {
    for (File f : file.listFiles()) {
      if (f.isDirectory())
        dirList.add(f);
      else
        fileList.add(f);
    }
    dirList.addAll(fileList);

  }

  private static Image getIconForFile(File file) throws IOException {
    Image icon;

    try {
      String mimeType = Files.probeContentType(file.toPath());
      if (mimeType == null) throw new IOException();

      String iconPath = "/graphics/filetreeicons/" + mimeType.replace('/', '-') + ".png";
      InputStream imageData = FiletreeOperations.class.getResourceAsStream(iconPath);
      if (imageData == null) throw new IOException();

      icon = new Image(imageData);

    } catch (IOException e) {
      System.err.println("[WARNING] Icon not found: " + file.getPath());

      // String iconPath = "/graphics/filetreeicons/file.png";
      String iconPath = "/graphics/filetreeicons/unknown.png";

      InputStream imageData = FileOperations.class.getResourceAsStream(iconPath);
      if (imageData == null) throw new IOException();

      icon = new Image(imageData);
    }
      
    return icon;
  }

  public static Path getPathOfTreeItem(TreeItem<String> item) throws FileNotFoundException {
    Path projectPath = 
      Model
        .getProjectPath()
        .orElseThrow(() -> new IllegalStateException());

    final String rootFolderName =
      projectPath
        .getFileName()
        .toString();

    String path = "";
    while (!rootFolderName.equals(item.getValue())) {
      path = File.separator + item.getValue() + path;
      item = item.getParent();
      if (item == null)
        throw new FileNotFoundException();
    }

    path = projectPath.toString() + path;

    Path pathToString = Paths.get(path);

    return pathToString;
  }  
}
