package com.usai.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;

import com.usai.redant.raimage.RedAntApplication;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

import static com.usai.util.Network.URL_UPLOAD;

/**
 * Created by ray on 13/06/2017.
 */

public class RAUploadManager {
    public int maxThread = 3;
    public int activeThread;
    public int maxRetry = 5;
    public int retryWaiting = 300;


    public Boolean wifiOnly = false;
    //    public Boolean autoStart=true;
//    public Boolean removeFinish=true;
//    public Boolean removeError=false;
    public QueueStatus queue_status;


    public static final int RESULT_BARCODE_ERROR = -50;

    public TaskStatus newtaskStatus = TaskStatus.TaskStatusWait;
    private ArrayList<Bundle> arr_queue;

    public ArrayList<Bundle> get_arr_queue() {
        return arr_queue;
    }

    //    private List<Bundle> operation_queue;
//    private ExecutorService es = Executors.newFixedThreadPool(3);//
    // .newFixedThreadPool();
//    private CountDownLatch latch = new CountDownLatch(maxThread);
    private RAOperationQueue operation_queue;

    public enum QueueStatus {
        QueueStatusDefault,
        QueueStatusAdd,
        QueueStatusError,
        QueueStatusFinishWithError,
        QueueStatusFinish
    }

    public enum TaskStatus {
        TaskStatusStop,
        TaskStatusStart,
        TaskStatusError,
        TaskStatusWait,
        TaskStatusFinish,
        //TaskStatusCancel,
    }

    public UIUpdateListener uiUpdateListener;

    public interface UIUpdateListener {
        //        void onProgress(long index, double percentage);
        void updateCell(long index, Bundle taskinfo);
//        void updateList();

        void updateList(ArrayList<Bundle> newlist);
//        void addTasks(ArrayList<Bundle> tasks);
//        void RemoveTasks(ArrayList<Bundle> tasks);

//        void onFinish(int code, String res/*, HashMap<String, List<String>> headers*/);
    }


//    class Poll implements Runnable {
//        public void run() {
//            // while (queue.size()>0) {
//            while (!operation_queue.isEmpty()) {
//                System.out.println(operation_queue.poll());
//            }
//            latch.countDown();
//        }
//    }

    public RAUploadManager() {
        queue_status = QueueStatus.QueueStatusDefault;


        SharedPreferences UMSetting = RedAntApplication.getInstance()
                .getSharedPreferences("UploadManager", 0);

        if (UMSetting != null) {
//            autoStart = UMSetting.getBoolean("auto_upload",false);
//            removeFinish = UMSetting.getBoolean("auto_rm_finish",false);
//            removeError = UMSetting.getBoolean("auto_rm_error",false);
            maxRetry = UMSetting.getInt("retry_count", 5);
            newtaskStatus = TaskStatus.values()[UMSetting.getInt("newtask_status", TaskStatus.TaskStatusWait.ordinal())];

            maxThread = UMSetting.getInt("max_thread", 3);

            wifiOnly = UMSetting.getBoolean("wifi_only", false);

        }
        operation_queue = new RAOperationQueue();
        operation_queue.setCallback(new RAOperationQueue.OperationCallback() {
            @Override
            public Boolean operate(final Bundle taskinfo) {


//
//                ConnectivityManager connManager = (ConnectivityManager) context
//                        .getSystemService(Context.CONNECTIVITY_SERVICE);
//
//                NetworkInfo networkInfo = connManager
//                        .getActiveNetworkInfo();
//                if (networkInfo == null)
//                {
//                    dbgUtil.Logd(
//                            "Current Network info",
//                            "can not get Active NetworkInfo!");
//                    false;
//                }
//                NetworkInfo.State netState = networkInfo
//                        .getState();
//                if (netState != NetworkInfo.State.CONNECTED)
//                {
//                    dbgUtil.Logd(
//                            "Current Network info",
//                            "not Connected!State="
//                                    + netState);
//                    return;
//                }
//                int iconntype = -1;
//                iconntype = networkInfo
//                        .getType();
//                SharedPreferences pref = RedAntApplication
//                        .getInstance()
//                        .getSharedPreferences(
//                                "UploadManager",
//                                0);
//
////															String aa = pref
////																	.getString(
////																			"aa",
////																			null);
////															String ea = pref
////																	.getString(
////																			"ea",
////																			null);
////															if (iconntype == ConnectivityManager.TYPE_WIFI)
////															{
////																if (!TextUtils
////																		.isEmpty(aa))
////																	RedAntApplication.active_address = aa;
////															}
////															else
////															{
////																if (!TextUtils
////																		.isEmpty(ea))
////																	RedAntApplication.active_address = ea;
////															}
//                boolean
//                        wifi_only
//                        =pref.getBoolean("wifi_only",
//                        true);
//
//                if
//                        (wifi_only
//                        == true
//                        && iconntype !=
//                        ConnectivityManager.TYPE_WIFI
//                        && iconntype !=
//                        9/* earthnet */)
//

                boolean ret = false;
                String path = taskinfo.getString("path");
                taskinfo.putInt("status", TaskStatus.TaskStatusStart.ordinal());
                String url = taskinfo.getString("url") + "" + URL_UPLOAD;

                int waiting = taskinfo.getInt("retry_waiting", 0);

                int newwaiting = waiting;
                if (newwaiting / 60.0 < 20)
                    newwaiting += retryWaiting;
                if (newwaiting > 1200)
                    newwaiting = 1200;
                taskinfo.putInt("retry_waiting", newwaiting);

                //                try{
                try {
                    Thread.currentThread().sleep(waiting * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
//                }catch(InterruptedException ie){
//                    ie.printStackTrace();
//                }
                JSONObject result = Network.UploadImage(path, taskinfo.getBundle("params"), url, new Network.FileUploadListener() {
                    @Override
                    public double percent_step() {
                        //进度刷新步进 3%
                        return 3.0;
                    }

                    @Override
                    public boolean interupt() {
//                        if(taskinfo.getBoolean("iscancel",false))
//                            return false;
                        return taskinfo.getBoolean("iscancel", false);
                    }

                    @Override
                    public void onProgress(long pro, double percentage) {


                        synchronized (this) {
                            Log.d("_synchronized", "UploadImage onProgress: " + percentage);
                            long timeStart = System.currentTimeMillis();
                            taskinfo.putDouble("progress", percentage);
                            if (uiUpdateListener != null) {
                                int index = arr_queue.indexOf(taskinfo);
//                            uiUpdateListener.onProgress(index,percentage);

                                uiUpdateListener.updateCell(index, taskinfo);
                            }
                            Log.d("_synchronized", "UploadImage onProgress: end" + (System.currentTimeMillis() - timeStart));
                        }


                    }

                    @Override
                    public void onFinish(int code, String res) {
                        Log.d("", "onFinish: ");

                    }
                });
                int r = 0;
                try {
                    r = result.getInt("result");


                    if (r == 2 || r == RESULT_BARCODE_ERROR) {
                        taskinfo.putInt("status", TaskStatus.TaskStatusFinish.ordinal());
                        if (r == 2)
                            taskinfo.putString("msg", "upload successful");
                        else {
                            String rmsg = result.getString("msg");
                            taskinfo.putString("msg", "warning: " + rmsg);
                        }
                    } else {
                        if (taskinfo.getInt("retry", 0) >= maxRetry) {
                            taskinfo.putInt("status", TaskStatus.TaskStatusError.ordinal());
                            taskinfo.putDouble("progress", 0.0);
                            String rmsg = result.getString("msg");
                            taskinfo.putString("msg", rmsg);
                        } else {
                            taskinfo.putInt("retry", taskinfo.getInt("retry", 0) + 1);
                            taskinfo.putInt("status", TaskStatus.TaskStatusWait.ordinal());
                            taskinfo.putDouble("progress", 0.0);
                            taskinfo.putString("msg", "connection lost, retry...");
                            ret = true;

                        }
                    }


                } catch (JSONException e) {
//                    String rmsg=result.getString("msg");
                    taskinfo.putInt("status", TaskStatus.TaskStatusError.ordinal());
                    taskinfo.putDouble("progress", 0.0);
                    taskinfo.putString("msg", "can not upload, please contact administrator.");
                    e.printStackTrace();
                } finally {
                    synchronized (this) {
                        Log.d("_synchronized", "UploadImage finally ");

                        long timeStart = System.currentTimeMillis();
                        if (uiUpdateListener != null) {
                            int index = arr_queue.indexOf(taskinfo);

                            uiUpdateListener.updateCell(index, taskinfo);
                        }
                        Log.d("_synchronized", "UploadImage finally finish" + (System.currentTimeMillis() - timeStart));

                    }
                }

                return ret;
//                int a=0;
//                System.out.println(a+"running  tid="+Thread.currentThread().getId());
//                int min=1000;
//                int max=5000;
//                int sleep=new Random().nextInt(max)%(max-min+1) + min;
//                try{
//                    Thread.currentThread().sleep(sleep);
//                }catch(InterruptedException ie){
//                    ie.printStackTrace();
//                }
//                System.out.println(a+"   "+sleep+"     finish  tid="+Thread.currentThread().getId());

            }

            @Override
            public void operateFinish(Bundle taskinfo) {

                TaskStatus status = TaskStatus.values()[taskinfo.getInt("status", 0)];

                //新增逻辑，对于成功上传的图片，从书记删除
                //taskinfo.getString("msg").indexOf("warning:")<0 没有匹配错误
                String path = filePath(taskinfo);
                File file = new File(path);
                //只有finish的task 可以删除图片

                if (file.exists() && taskinfo.getInt("status") == TaskStatus.TaskStatusFinish.ordinal() && taskinfo.getString("msg").indexOf("warning:") < 0) {
                    String filepath = file.getAbsolutePath();
                    file.delete();
                    RAUtil.updateGallery(filepath);
                }
                ///////////////////////////////////////////////

                boolean removefromlist = false;
//                if (status==TaskStatus.TaskStatusFinish&&removeFinish)
//                    removefromlist=true;
//                else if (status==TaskStatus.TaskStatusError&&removeError)
//                    removefromlist=true;

                synchronized (this) {

                    Log.d("_synchronized", "OperationCallback operateFinish: ");
                    long timeStart = System.currentTimeMillis();
                    if (removefromlist) {

                        removeTask(taskinfo);
//                            arr_queue.remove(taskinfo);
//                        if(uiUpdateListener!=null)
//                            uiUpdateListener.updateList();


                    } else {
                        saveTasks();
                    }

                    Log.d("_synchronized", "OperationCallback operateFinish: end" + (System.currentTimeMillis() - timeStart));


//                        saveTasks();


                }


            }
        });

        //            operation_queue = new List<Bundle>() {};

        loadTask();

    }

    private void loadTask() {
        stopAllTasks();
        arr_queue = new ArrayList<Bundle>();


        Log.d("_RAIMAGE", "saveTasks: RAUploadManager");

        SharedPreferences pref = RedAntApplication.getInstance()
                .getSharedPreferences("RA Image", 0);
        try {
            String tasksBase64 = pref.getString("task_list", "");


//            ArrayList<String> wrap_arr = new ArrayList<String>();
//            for( Bundle b:arr_queue)
//            {
//                String sjson=RAUtil.Bundle2Json(b).toString();
//                Log.d("_RAIMAGE", "saveTasks: "+sjson);
//                wrap_arr.add(sjson);
//            }
//
//            ByteArrayOutputStream baos = new ByteArrayOutputStream();
//            ObjectOutputStream oos = new ObjectOutputStream(baos);
//            oos.writeObject(wrap_arr);
//
//            String tasksBase64 = android.util.Base64.encodeToString(baos.toByteArray(), android.util.Base64.DEFAULT);//new String(Base64.encodeBase64(baos.toByteArray()));
//
//
//            editor.putString("task_list", tasksBase64);
//
//
//            editor.commit();

            if (tasksBase64.length() > 0) {
                byte[] decode = Base64.decode(tasksBase64, Base64.DEFAULT);
                ByteArrayInputStream bais = new ByteArrayInputStream(decode);

                ObjectInputStream ois = null;

                ois = new ObjectInputStream(bais);

                ArrayList<String> arr_load = (ArrayList<String>) ois.readObject();
                for (String s : arr_load) {
                    Log.d("_RAIMAGE", "loadTask: " + s);
                    JSONObject jsobj = new JSONObject(s);
                    Bundle b = RAUtil.Json2Bundle(jsobj);
                    arr_queue.add(b);
//                                String sjson=RAUtil.Bundle2Json(b).toString();

//                wrap_arr.add(sjson);
                }
            }


        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        for (Bundle b : arr_queue) {

            TaskStatus status = TaskStatus.values()[b.getInt("status", 0)];

            if (status != TaskStatus.TaskStatusFinish && status != TaskStatus.TaskStatusError)
                startTask(b);
        }
//            int a = 0;
        // 此处缺少读取持久话保存任务队列的实现。
    }

    public void addTask(Bundle task) {

        synchronized (this) {
            Log.d("_synchronized", "addTask: ");
            long timeStart = System.currentTimeMillis();
            arr_queue.add(task);
            saveTasks();
            Log.d("_synchronized", "addTask: end" + (System.currentTimeMillis() - timeStart));
        }
        if (newtaskStatus == TaskStatus.TaskStatusWait) {
            startTask(task);
        }
    }

    ;

    public void addTasks(ArrayList<Bundle> tasks) {

        synchronized (this) {
            Log.d("_synchronized", "addTasks: ");
            long timeStart = System.currentTimeMillis();
            arr_queue.addAll(tasks);
            saveTasks();

            Log.d("_synchronized", "addTasks: end" + (System.currentTimeMillis() - timeStart));

        }
        if (newtaskStatus == TaskStatus.TaskStatusWait) {
            for (Bundle task : tasks) {
                startTask(task);
            }

        }

    }

    ;

    public void startTask(Bundle task) {

        task.putBoolean("iscancel", false);


        boolean canstart = true;

        ConnectivityManager connManager = (ConnectivityManager) RedAntApplication.getInstance()
                .getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo networkInfo = connManager
                .getActiveNetworkInfo();
        if (networkInfo == null) {
            dbgUtil.Logd(
                    "Current Network info",
                    "can not get Active NetworkInfo!");
            canstart = false;
        } else {
            NetworkInfo.State netState = networkInfo
                    .getState();
            if (netState != NetworkInfo.State.CONNECTED) {
                dbgUtil.Logd(
                        "Current Network info",
                        "not Connected!State="
                                + netState);
                canstart = false;
            }
            int iconntype = -1;
            iconntype = networkInfo
                    .getType();

            if (wifiOnly == true
                    && iconntype !=
                    ConnectivityManager.TYPE_WIFI
                    && iconntype !=
                    9/* earthnet */) {
                canstart = false;
            }
        }

        if (canstart) {

            task.putInt("retry_waiting", 0);
            task.putInt("status", TaskStatus.TaskStatusWait.ordinal());
            operation_queue.addOperation(task);
        } else {
            task.putInt("status", TaskStatus.TaskStatusStop.ordinal());
            if (uiUpdateListener != null) {
                int index = arr_queue.indexOf(task);
//                            uiUpdateListener.onProgress(index,percentage);

                uiUpdateListener.updateCell(index, task);
            }

        }


    }

    ;

    public void clearTask() {
        ArrayList<Bundle> remove = new ArrayList<Bundle>();
        for (Bundle b : arr_queue) {
//            if(TaskStatus.values()[b.getInt("status",0)]==TaskStatus.TaskStatusStart||TaskStatus.values()[b.getInt("status",0)]==TaskStatus.TaskStatusWait)
//                continue;

            if (TaskStatus.values()[b.getInt("status", 0)] == TaskStatus.TaskStatusFinish || TaskStatus.values()[b.getInt("status", 0)] == TaskStatus.TaskStatusError)
                remove.add(b);
//            removeTask(b);
        }
        removeTasks(remove);


    }

    public void removeTask(Bundle task) {


        synchronized (this) {
            Log.d("_synchronized", "removeTask");
            long timeStart = System.currentTimeMillis();
            arr_queue.remove(task);
            saveTasks();


            String path = filePath(task);
            File file = new File(path);
            //只有finish的task 可以删除图片
            if (file.exists() && task.getInt("status") == TaskStatus.TaskStatusFinish.ordinal()) {
                String filepath = file.getAbsolutePath();
                file.delete();
                RAUtil.updateGallery(filepath);
            }

            if (uiUpdateListener != null)
                uiUpdateListener.updateList(arr_queue);

            Log.d("_synchronized", "removeTask: end" + (System.currentTimeMillis() - timeStart));
        }


    }

    ;

    public void removeTasks(List<Bundle> tasks) {

        synchronized (this) {
            Log.d("_synchronized", "removeTasks: ");
            long timeStart = System.currentTimeMillis();
            arr_queue.removeAll(tasks);
            saveTasks();
            for (Bundle task : tasks) {

                String path = filePath(task);
                File file = new File(path);
                if (file.exists() && task.getInt("status") == TaskStatus.TaskStatusFinish.ordinal()) {
                    String filepath = file.getAbsolutePath();
                    file.delete();
                    RAUtil.updateGallery(filepath);
                }
            }
            if (uiUpdateListener != null)
                uiUpdateListener.updateList(arr_queue);


            Log.d("_synchronized", "removeTasks: end" + (System.currentTimeMillis() - timeStart));
        }

    }

    ;

    public void stopAllTasks() {
        if (arr_queue == null)
            return;
        for (Bundle task : arr_queue) {
            stopTask(task);
        }
    }

    ;

    public void stopTask(Bundle task) {
        if (task.getInt("status") != TaskStatus.TaskStatusStart.ordinal() && task.getInt("status") != TaskStatus.TaskStatusWait.ordinal())
            return;

        task.putBoolean("iscancel", true);
//        long tid=task.getLong("tid",-1);
//        if(tid>0)
//        {
//
//
//        }
//        task.tet("tid",Thread.currentThread().getId());

//        RAUploadOperation


    }

    public void saveTasks() {

        Log.d("_RAIMAGE", "saveTasks: RAUploadManager");

        SharedPreferences pref = RedAntApplication.getInstance()
                .getSharedPreferences("RA Image", 0);
        SharedPreferences.Editor editor = pref.edit();

        try {

            ArrayList<String> wrap_arr = new ArrayList<String>();
            for (Bundle b : arr_queue) {
                String sjson = RAUtil.Bundle2Json(b).toString();
                Log.d("_RAIMAGE", "saveTasks: " + sjson);
                wrap_arr.add(sjson);
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(wrap_arr);

            String tasksBase64 = android.util.Base64.encodeToString(baos.toByteArray(), android.util.Base64.DEFAULT);//new String(Base64.encodeBase64(baos.toByteArray()));


            editor.putString("task_list", tasksBase64);


            editor.commit();

//            byte[] decode=Base64.decode(personBase64,Base64.DEFAULT);
//            ByteArrayInputStream bais= new ByteArrayInputStream(decode);
//
//            ObjectInputStream ois = new ObjectInputStream(bais);
//            ArrayList<String> arr_load=(ArrayList<String>)ois.readObject();
//            int a = 0;

        } catch (Exception e) {
            e.printStackTrace();

        }


//        if (m_swSave.isChecked()&&!TextUtils.isEmpty(encryptPass)&&!TextUtils.isEmpty(encryptUser))
//        {
//            editor.putString("user", encryptUser);
//            editor.putString("password", encryptPass);
//            editor.putBoolean("kepppass", true);
//        }
//        else
//        {
//            editor.putString("user", null);
//            editor.putString("password", null);
//            editor.putBoolean("kepppass", false);
//        }
//
//        editor.puts
//
//        editor.commit();

    }

    ;


    private String filePath(Bundle task) {
//        String path = Environment.getExternalStorageDirectory().getPath();
//        path+="/"+task.getString("path");
//        path+="/"+task.getString("file");

        return task.getString("path", "");
    }


}
