package kz.arta.synergy.workflow.mobile.android.files.manager;

import android.util.Base64;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.utils.Logger;

/**
 * Created by neox on 05.10.15.
 * Менеджер по работе с хранилищем
 */
public class FilesManager {

    /**
     * Данные пользователя
     */
    private Person person;

    /**
     * Конструктор
     *
     * @param person данные пользователя
     */
    public FilesManager(Person person) {
        this.person = person;
    }

    /**
     * Метод возвращает HttpUrlConnection для выполнения запросов
     *
     * @param url url на апи метод
     * @return HttpURLConnection
     */
    private HttpURLConnection getConnection(String url) {
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Accept", "application/json; charset=utf-8");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Cache-Control", "no-cache");
            String basicAuth = "Basic " + new String(Base64.encode(person.getAuth().getBytes(), Base64.NO_WRAP));
            conn.setRequestProperty("Authorization", basicAuth);
            conn.setUseCaches(false);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            return conn;
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Метод возвращает результат выполнения запроса
     *
     * @param conn HttpURLConnection
     * @return результат выполнения запроса
     */
    private String getResponse(HttpURLConnection conn) {
        try {
            InputStream is = conn.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuilder response = new StringBuilder();
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Удаление элемента хранилища
     *
     * @param elementID идентификатор элемента
     * @return сообщение характерезующее успешность выполнения
     */
    public String remove(String elementID) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/remove");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.writeBytes("elementID=" + URLEncoder.encode(elementID, "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Переименование элемента хранилища
     *
     * @param elementID   идентификатор элемента
     * @param elementName новое имя для элемента
     * @return сообщение характерезующее успешность выполнения
     */
    public String rename(String elementID, String elementName) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/rename");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.writeBytes("elementID=" + URLEncoder.encode(elementID, "utf-8") + "&");
            request.writeBytes("elementName=" + URLEncoder.encode(elementName, "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Создание новой папки
     *
     * @param folderID   идентификатор родителя
     * @param folderName новое имя папки
     * @return сообщение характерезующее успешность выполнения
     */
    public String newFolder(String folderID, String folderName) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/create");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.writeBytes("folderID=" + URLEncoder.encode(folderID, "utf-8") + "&");
            request.writeBytes("folderName=" + URLEncoder.encode(folderName, "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Добавление файла в хранилище
     *
     * @param folderID      идентификатор родителя
     * @param name          имя файла
     * @param path          временный путь до файла на сервере
     * @return сообщение характерезующее успешность выполнения
     */
    public String newFile(String folderID, String name, String path) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/add");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.writeBytes("folderID=" + URLEncoder.encode(folderID, "utf-8") + "&");
            request.writeBytes("name=" + URLEncoder.encode(name, "utf-8") + "&");
            request.writeBytes("path=" + URLEncoder.encode(path, "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            Logger.v("EXC = " + exc.getLocalizedMessage());
            return null;
        }
    }

    /**
     * Метод копирует файл в работу/документ из хранилища
     *
     * @param documentID идентификатор документа, куда копируется файл
     * @param fileID     идентификатор файла
     * @return сообщение характерезующее успешность выполнения
     */
    public String copy(String documentID, String fileID, String container) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/copy");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.writeBytes("documentID=" + URLEncoder.encode(documentID, "utf-8") + "&");
            request.writeBytes("fileID=" + URLEncoder.encode(fileID, "utf-8") + "&");
            request.writeBytes("container=" + URLEncoder.encode(container, "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Метод перемещает файл внутри хранилище
     *
     * @param elementID идентификатор элемента
     * @param folderID  идентификатор папки, куда перемещается файл
     * @return сообщение характерезующее успешность выполнения
     */
    public String move(String elementID, String folderID) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/move");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.writeBytes("elementID=" + URLEncoder.encode(elementID, "utf-8") + "&");
            request.writeBytes("folderID=" + URLEncoder.encode(folderID, "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Добавление файла в форму
     *
     * @param filePath путь
     * @param dataUUID идентификатор данных по форме
     * @return
     */
    public String addFileToForm(String filePath, String dataUUID, String fileName) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/asffile/addFile?filePath=" +
                    filePath + "&dataUUID=" + dataUUID + "&fileName=" + fileName);
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }

    /**
     * Метод используется для поиска файлов в хранилище
     *
     * @param params параметры поиска
     * @return сообщение характерезующее успешность выполнения
     */
    public String search(SearchParams params) {
        try {
            HttpURLConnection conn = getConnection(person.getHost() + "rest/api/storage/search");
            DataOutputStream request = new DataOutputStream(conn.getOutputStream());
            if (params.getContains() != null) {
                request.writeBytes("contains=" + URLEncoder.encode(params.getContains(), "utf-8") + "&");
            }
            if (params.getFolderID() != null) {
                request.writeBytes("folderID=" + URLEncoder.encode(params.getFolderID(), "utf-8") + "&");
            }
            if (params.getAiType() != null) {
                request.writeBytes("aiType=" + URLEncoder.encode(params.getAiType(), "utf-8") + "&");
            }
            if (params.getModifiedFrom() != null && params.getModifiedTo() != null) {
                request.writeBytes("modifiedFrom=" + URLEncoder.encode(params.getModifiedFrom(), "utf-8") + "&");
                request.writeBytes("modifiedTo=" + URLEncoder.encode(params.getModifiedTo(), "utf-8") + "&");
            }
            request.writeBytes("firstResult=" + URLEncoder.encode(String.valueOf(params.getFirstResult()), "utf-8") + "&");
            request.writeBytes("maxResult=" + URLEncoder.encode(String.valueOf(SearchParams.COUNT_FILES), "utf-8") + "&");
            request.writeBytes("sortType=" + URLEncoder.encode(String.valueOf(params.getSortType()), "utf-8") + "&");
            request.flush();
            request.close();
            return getResponse(conn);
        } catch (Exception exc) {
            return null;
        }
    }
}
