package kz.arta.synergy.workflow.mobile.android.common.offline.get;

import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.util.Base64;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import kz.arta.synergy.workflow.mobile.android.R;
import kz.arta.synergy.workflow.mobile.android.attachments.models.AllAttachmentsItem;
import kz.arta.synergy.workflow.mobile.android.attachments.models.AttachmentItem;
import kz.arta.synergy.workflow.mobile.android.common.SettingsConst;
import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.requests.RestClient;
import kz.arta.synergy.workflow.mobile.android.common.utils.Const;
import kz.arta.synergy.workflow.mobile.android.common.utils.MyApplication;
import kz.arta.synergy.workflow.mobile.android.works.models.WorkItem;

/**
 * Created by neox on 04.07.14.
 */
public class WorkAttachmentsTable extends SQLiteOpenHelper {

    private static final String NEVER = "NEVER";
    private static final String ALWAYS = "ALWAYS";
    private static final String WIFI = "WIFI";
    private static final String MOBILE = "MOBILE";

    private SQLiteDatabase db = getWritableDatabase();
    private static final String TABLE_NAME = "Attachments";
    private static final String TABLE = "create table " + TABLE_NAME + " ("
            + "type text,"
            + "actionID text,"
            + "uuid text,"
            + "name text,"
            + "is_editable text,"
            + "created_label text,"
            + "created text,"
            + "icon text,"
            + "filepath text"
            + ");";

    private Context context;
    private Person person;

    public WorkAttachmentsTable(Context context) {
        super(context, TABLE_NAME, null, 1);
        this.context = context;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {

    }

    public void add(String jsonString, String actionID) throws Exception {

        ContentValues cv = new ContentValues();

        AllAttachmentsItem[] allAttachmentItems = RestClient.getGson().fromJson(jsonString, AllAttachmentsItem[].class);

        // создаем директорию куда будем складывать все загруженные вложения
        File folder = new File(Environment.getExternalStorageDirectory() + File.separator + Const.ATTACHMENT_DIRECTORY_NAME);
        boolean createdDir = true;
        if (!folder.exists()) {
            createdDir = folder.mkdir();
        }

        // проверяем какое соединение используется сейчас
        String checkConnection = checkInternet();

        String download = "";

        SharedPreferences settings = context.getSharedPreferences(SettingsConst.DEFAULT_NAME_SETTINGS, Context.MODE_PRIVATE);

        if (settings.contains(SettingsConst.DOWNLOAD_ATTACHMENTS)) {
            if (settings.getString(SettingsConst.DOWNLOAD_ATTACHMENTS, "").equals(context.getString(R.string.never))) {
                download = NEVER;
            } else if (settings.getString(SettingsConst.DOWNLOAD_ATTACHMENTS, "").equals(context.getString(R.string.always))) {
                download = ALWAYS;
            } else {
                download = WIFI;
            }
        }

        if (!allAttachmentItems[0].getAttachments().isEmpty()) {
            List<AttachmentItem> attach = allAttachmentItems[0].getAttachments();
            for (AttachmentItem anAttach : attach) {
                String filePath = downloadAttachment(download, checkConnection, createdDir, anAttach);
                cv.put("type", "attachments");
                cv.put("actionID", actionID);
                cv.put("uuid", anAttach.getUuid());
                cv.put("name", anAttach.getName());
                cv.put("is_editable", anAttach.getIs_editable());
                cv.put("created_label", anAttach.getCreated_label());
                cv.put("created", anAttach.getCreated());
                cv.put("icon", anAttach.getIcon());
                cv.put("filepath", filePath);
                db.insert(TABLE_NAME, null, cv);
            }
        }

        if (!allAttachmentItems[1].getWork_files().isEmpty()) {
            List<AttachmentItem> work = allAttachmentItems[1].getWork_files();
            for (AttachmentItem aWork : work) {
                String filePath = downloadAttachment(download, checkConnection, createdDir, aWork);
                cv.put("type", "workfiles");
                cv.put("actionID", actionID);
                cv.put("uuid", aWork.getUuid());
                cv.put("name", aWork.getName());
                cv.put("is_editable", aWork.getIs_editable());
                cv.put("created_label", aWork.getCreated_label());
                cv.put("created", aWork.getCreated());
                cv.put("icon", aWork.getIcon());
                cv.put("filepath", filePath);
                db.insert(TABLE_NAME, null, cv);
            }
        }
    }

    private String downloadAttachment(String download, String checkConnection, boolean createdDir, AttachmentItem attach) {
        String fileName = null;
        if (download.equals(ALWAYS)) {
            if (checkConnection.equals(WIFI) || checkConnection.equals(MOBILE)) {
                if (createdDir) {
                    fileName = downloadFile(person.getHost() + "rest/api/storage/pdf/get?identifier="
                            + attach.getUuid() + "&locale=" + MyApplication.getLang(), attach.getUuid() + attach.getName());
                }
            }
        } else if (download.equals(WIFI)) {
            if (checkConnection.equals(WIFI)) {
                if (createdDir) {
                    fileName = downloadFile(person.getHost() + "rest/api/storage/pdf/get?identifier="
                            + attach.getUuid() + "&locale=" + MyApplication.getLang(), attach.getUuid());
                }
            }
        }
        return fileName;
    }

    public List<AttachmentItem> get(String actionID) {
        List<AttachmentItem> result = new ArrayList<>();
        Cursor c = null;
        try {
            c = db.rawQuery("select * from " + TABLE_NAME + " where actionID = ?", new String[]{actionID});
            if (c.moveToFirst()) {
                do {
                    AttachmentItem attachmentItem = new AttachmentItem();
                    attachmentItem.setType(c.getString(c.getColumnIndex("type")));
                    attachmentItem.setActionID(c.getString(c.getColumnIndex("actionID")));
                    attachmentItem.setUuid(c.getString(c.getColumnIndex("uuid")));
                    attachmentItem.setName(c.getString(c.getColumnIndex("name")));
                    attachmentItem.setCreated(c.getString(c.getColumnIndex("created")));
                    attachmentItem.setCreated_label(c.getString(c.getColumnIndex("created_label")));
                    attachmentItem.setIs_editable(c.getString(c.getColumnIndex("is_editable")));
                    attachmentItem.setIcon(c.getString(c.getColumnIndex("icon")));
                    attachmentItem.setFilepath(c.getString(c.getColumnIndex("filepath")));
                    result.add(attachmentItem);
                } while (c.moveToNext());
            }
            return result;
        } catch (Exception exc) {
            return result;
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }

    public boolean deleteAttachment(String nodeUUID) {
        try {
            db.delete(TABLE_NAME, "uuid = " + "\"" + nodeUUID + "\"", null);
            return true;
        } catch (Exception exc) {
            return false;
        }
    }

    public void removeWorksByArray(List<WorkItem> works) {
        try {
            for (WorkItem work : works) {
                db.delete(TABLE_NAME, "actionID = " + "\"" + work.getActionID() + "\"", null);
            }
        } catch (Exception exc) {
            // handling error
        }
    }

    public boolean removeAll() {
        try {
            db.delete(TABLE_NAME, null, null);
            return true;
        } catch (Exception exc) {
            return false;
        }
    }

    public String getFilePathByUUID(String uuid) {
        String result = null;
        Cursor c = null;
        try {
            c = db.rawQuery("select * from " + TABLE_NAME + " where uuid = ?", new String[]{uuid});
            if (c.moveToFirst()) {
                do {
                    result = c.getString(c.getColumnIndex("filepath"));
                } while (c.moveToNext());
            }
            c.close();
            return result;
        } catch (Exception exc) {
            return result;
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }

    public String getFilePathByDate(String date) {
        String result = null;
        Cursor c = null;
        try {
            c = db.rawQuery("select * from " + TABLE_NAME + " where created = ?", new String[]{date});
            if (c.moveToFirst()) {
                do {
                    result = c.getString(c.getColumnIndex("filepath"));
                } while (c.moveToNext());
            }
            c.close();
            return result;
        } catch (Exception exc) {
            return result;
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }

    private String checkInternet() {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();
        for (NetworkInfo ni : netInfo) {
            if (ni.getTypeName().equalsIgnoreCase(WIFI) && ni.isConnected()) {
                return WIFI;
            }
            if (ni.getTypeName().equalsIgnoreCase(MOBILE) && ni.isConnected()) {
                return MOBILE;
            }
        }
        return "NO";
    }

    private String downloadFile(final String url, final String uuid) {

        int bufferLength;
        String contentDisposition = null;
        URLConnection uConn;

        try {

            URL urls = new URL(url);
            uConn = urls.openConnection();

            String basicAuth = "Basic " + new String(Base64.encode(person.getAuth().getBytes(), Base64.NO_WRAP));
            uConn.setRequestProperty("Authorization", basicAuth);
            Map headerFields = uConn.getHeaderFields();
            Set headers = headerFields.entrySet();

            for (Object header : headers) {
                Map.Entry map = (Map.Entry) header;
                if ("Content-Disposition".equals(map.getKey())) {
                    contentDisposition = map.getValue().toString();
                }
            }

            if (contentDisposition != null) {

                StringBuilder buffer = new StringBuilder(contentDisposition);
                String fileName;

                if (buffer.indexOf("\"") != -1) {
                    fileName = buffer.substring(buffer.indexOf("filename") + 10, buffer.length() - 2);
                } else {
                    fileName = buffer.substring(buffer.indexOf("filename") + 9, buffer.length() - 1);
                }

                InputStream is = uConn.getInputStream();
                BufferedInputStream inStream = new BufferedInputStream(is, 1024);

                FileOutputStream outStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()
                        + File.separator + Const.ATTACHMENT_DIRECTORY_NAME + File.separator + uuid + fileName);

                byte[] buff = new byte[1024];

                while ((bufferLength = inStream.read(buff)) > 0) {
                    outStream.write(buff, 0, bufferLength);
                }

                outStream.flush();
                outStream.close();
                inStream.close();

                return Environment.getExternalStorageDirectory().getPath()
                        + File.separator + Const.ATTACHMENT_DIRECTORY_NAME + File.separator + uuid + fileName;
            }

            return null;

        } catch (IOException e) {
            return null;
        }
    }
}
