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

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Base64;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
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.R;
import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.requests.RestClient;

/**
 * Created by neox on 09.10.15.
 * Класс используется для добавления файла на сервер
 */
public class FileUpload extends AsyncTask<Void, Integer, String> {

    /**
     * Диалог отображающий прогресс добавления
     */
    private ProgressDialog progressDialog;

    /**
     * Пользователь
     */
    private Person person;

    /**
     * Активити из которого производится запуск
     */
    private Activity activity;

    /**
     * Имя файла
     */
    private String name;

    /**
     * Путь до файла лежащего на устройстве
     */
    private String path;

    /**
     * Конструктор
     *
     * @param activity текущее активити
     * @param person   пользователь
     * @param name     имя добавляемого файла
     * @param path     абсолютный путь до файла лежащего на устройстве
     */
    public FileUpload(Activity activity, Person person, String name, String path) {
        this.activity = activity;
        this.person = person;
        this.name = name;
        this.path = path;
    }

    @Override
    protected void onPreExecute() {
        progressDialog = new ProgressDialog(activity);
        progressDialog.setMessage(activity.getString(R.string.please_wait));
        progressDialog.setCancelable(false);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.show();
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(String result) {
        hideProgressBar();
        super.onPostExecute(result);
    }

    @Override
    protected String doInBackground(Void... voids) {
        return uploadFile();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        if (progressDialog != null) {
            progressDialog.setProgress(values[0] / 1024);
        }
        super.onProgressUpdate(values);
    }

    protected void hideProgressBar() {
        if (progressDialog != null) {
            progressDialog.dismiss();
        }
    }

    /**
     * Метод создает на сервере файл и дописывает в него данные
     *
     * @return абсолютный путь до созданного файла на сервере
     */
    public String uploadFile() {
        try {
            URL url = new URL(person.getHost() + "rest/api/storage/start_upload?locale=ru");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            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);
            String output;
            StringBuilder contactsInfo = new StringBuilder();
            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
            while ((output = br.readLine()) != null) {
                contactsInfo.append(output);
            }
            conn.disconnect();
            String tmpFilePath = RestClient.getGson().fromJson(contactsInfo.toString(), F.class).file;
            String boundary = "qweasdzxczxcasdqwe";
            String crlf = "\r\n";
            String twoHyphens = "--";
            FileInputStream fin = new FileInputStream(path);
            File file = new File(path);
            if (progressDialog != null) {
                progressDialog.setMax((int) file.length() / 1024);
            }
            int partSize = 1024 * 100;
            byte[] bytes = new byte[partSize];
            int position = 0;
            int read = 0;
            while ((read = fin.read(bytes, 0, partSize)) != -1) {
                if (progressDialog == null) {
                    publishProgress(position);
                }
                byte[] readBytes = new byte[read];
                System.arraycopy(bytes, 0, readBytes, 0, read);
                position += read;
                url = new URL(person.getHost() + "rest/api/storage/upload_part?file=" + URLEncoder.encode(tmpFilePath, "utf-8"));
                conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Accept", "application/json; charset=utf-8");
                conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
                conn.setRequestProperty("Connection", "Keep-Alive");
                conn.setRequestProperty("Cache-Control", "no-cache");
                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);
                DataOutputStream request = new DataOutputStream(conn.getOutputStream());
                request.writeBytes(twoHyphens + boundary + crlf);
                request.writeBytes("Content-Disposition: form-data; name=\"body\";filename=\"" + URLEncoder.encode(name, "utf-8") + "\"" + crlf);
                request.writeBytes(crlf);
                request.write(Base64.encode(bytes, Base64.NO_WRAP));
                request.writeBytes(crlf);
                request.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
                request.flush();
                request.close();
                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 tmpFilePath;
        } catch (Exception exc) {
            return null;
        }
    }

    class F {
        String file;
    }
}
