/*
 * Copyright (c) 2016 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL).  See the LICENSE file in the root
 * directory for license terms.  You may choose either license, or both.
 */
 
package com.oracle.iot.sample;

import static android.R.attr.path;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;
import android.view.View;
import android.widget.EditText;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;

public class FileManager {
    private final Activity activity;
    private final static String TAG = "FileManager";
    private final static String DIRECTORY_TAG = "DIR  ";
    private final static String FILE_TAG = "FILE ";
    private final static String TAS_TAG = "TAS  ";
    private final static String UP_TAG = "UP";

    //File path = new File("/");
    static File currentDirectory = new File(Environment.getExternalStorageDirectory() + "");
    // Check if the first level of the directory structure is the one showing
    private Boolean isRoot = false;
    private final FileListOptions opts;
    AlertDialog fileSelectionDialog;

    public FileManager(Activity activity) {
        this(activity, null);
    }
    
    public FileManager(Activity activity, FileListOptions opts) {
        this.activity = activity;
        if (opts == null) {
            this.opts = new FileListOptions();
        } else {
            this.opts = opts;
        }
        if (this.activity != null && this.opts.showDialog()) {
            buildDialog();
        }
    }

    private void buildDialog() {
        final String[] fileList = getFileList();

        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder = builder.setTitle("Please select a file");
        if (opts.showCreateFileButton()) {
            builder = builder.setPositiveButton("Create New", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    LayoutInflater li = LayoutInflater.from(activity);
                    View promptsView = li.inflate(R.layout.dialog_prompt, null);
                    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                                    activity);

                    alertDialogBuilder.setView(promptsView);

                    final EditText userInput = (EditText) promptsView
                                    .findViewById(R.id.newFile);

                    // set dialog message
                    alertDialogBuilder
                        .setCancelable(false)
                        .setPositiveButton("OK",
                         new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,int id) {
                                try {
                                    if (!TextUtils.isEmpty(userInput.getText())) {
                                        Log.d(TAG, "New file " +  userInput.getText().toString());
                                        File newFile = new File(currentDirectory, userInput.getText().toString());
                                        newFile.createNewFile();
                                    } else {
                                        Log.d(TAG, "Empty user input");
                                    }
                                    buildDialog();
                                    showDialog();
                                } catch (IOException ex) {
                                    Log.d(TAG, "Can't create a new file");
                                }
                            }
                          })
                        .setNegativeButton("Cancel",
                          new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,int id) {
                                dialog.cancel();
                            }
                          });

                    AlertDialog alertDialog = alertDialogBuilder.create();
                    alertDialog.show();
                }
            });
        }

        builder = builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // User cancelled the dialog
            }
        });
        builder = builder.setItems(fileList, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // If user presses first button and FileManager has navigation
                if (which == 0 && opts.hasNavigation() && fileList[which].equals(UP_TAG)) {
                    // Go up
                    currentDirectory = currentDirectory.getParentFile();
                    if (currentDirectory.getParentFile() == null) {
                        isRoot = true;
                    }
                    buildDialog();
                    showDialog();
                    return;
                }
                File currentFile = undecorate(fileList[which]);
                if (currentFile.isDirectory() && opts.hasNavigation()) {
                    currentDirectory = currentFile;
                    isRoot = false;
                    buildDialog();
                    showDialog();
                } else {
                    if (fileListener != null) {
                        fileListener.fileSelected(currentFile);
                    }
                    fileSelectionDialog.dismiss();
                }
            }
        });

        fileSelectionDialog = builder.create();
    }

    public void showDialog() {
        fileSelectionDialog.show();
    }

    public String[] getFileList() {
        if (!currentDirectory.exists()) {
            Log.e(TAG, "Path does not exist: " + currentDirectory.getAbsolutePath());
            currentDirectory = new File("/");
            isRoot = true;
        }
        File[] files = currentDirectory.listFiles(opts.getFilter());
        if (files == null)
            files = new File[0];
        List<String> fileList = new ArrayList<String>(files.length);
        // If FileManager can goes to up directory level
        if (opts.hasNavigation() && !isRoot
                && currentDirectory.getParentFile() != null
                && currentDirectory.getParentFile().exists()) {
        // Then FileManager shows UP directory
            fileList.add(UP_TAG);
        }
        for (File current : files) {
            fileList.add(decorate(current));
        }
        return fileList.toArray(new String[fileList.size()]);
    }
    
    public String decorate(File file) {
        if (opts.showTypes()) {
            if (file.isDirectory()) {
                return DIRECTORY_TAG + file.getName();
            } else {
                if (file.getName().endsWith(".conf") || file.getName().endsWith(".bks")
                         || file.getName().endsWith(".upf")) {
                    return TAS_TAG + file.getName();
                } else {
                    return FILE_TAG + file.getName();
                }
            }
        } else {
            return file.getName();
        }
    }
    
    public File undecorate(String file) {
        if (opts.showTypes()) {
            file = file.substring(file.lastIndexOf(" ")+1);
        }
        return new File(currentDirectory, file);
    }

    public static void copyFile(File source, File dest) {
        InputStream input = null;
        OutputStream output = null;
        try {

            input = new FileInputStream(source);
            output = new FileOutputStream(dest);
            byte[] buf = new byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buf)) > 0) {
                output.write(buf, 0, bytesRead);
            }
            input.close();
            output.close();
        }catch(Exception e){

        }
    }

    public File getCurrentDirectory() {
        return currentDirectory;
    }

    // file selection event handling
    public interface FileSelectedListener {
        void fileSelected(File file);
    }
    public FileManager setFileListener(FileSelectedListener fileListener) {
        this.fileListener = fileListener;
        return this;
    }
    private FileSelectedListener fileListener;
    
    public static class FileListOptions {
        public FileListOptions() {
        }
        public FileFilter getFilter() {
            return new FileFilter() {
            @Override
            public boolean accept(File file) {
                // Accept not hidden files and directories
                    return (file.isFile() && file.canRead())
                        || file.isDirectory()
                        && !file.isHidden();
                }
            };
        }
        public boolean hasNavigation() {
            return true;
        }
        public boolean showTypes() {
            return true;
        }
        public boolean showDialog() {
            return true;
        }
        public boolean showCreateFileButton() {
            return true;
        }
    }
}