package com.gh.gamecenter.manager;

import android.content.Context;

import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.loghub.LoghubUtils;
import com.gh.gamecenter.common.utils.Installation;
import com.gh.common.util.LogUtils;
import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.db.DataCollectionDao;
import com.gh.gamecenter.db.info.DataCollectionInfo;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class DataCollectionManager {

    private Context mContext;
    private DataCollectionDao dao;
    private boolean isUploading;

    private DataCollectionManager() {
        mContext = HaloApp.getInstance().getApplicationContext();
        dao = new DataCollectionDao(mContext);
        isUploading = false;
    }

    public static void onEvent(Context context, String type, Map<String, Object> map, boolean isUpload) {
        AppExecutor.getIoExecutor().execute(() -> {
            map.put("createdOn", Utils.getTime(context));
            if (isUpload) {
                DataCollectionManager.getInstance().realTimeUpload(type, map);
            } else {
                onEvent(type, new JSONObject(map).toString(), false);
            }
        });
    }

    /*
     * 实时上传
     */
    private void realTimeUpload(final String type, Map<String, Object> map) {
        String version = PackageUtils.getGhVersionName();
        String user = Installation.getUUID(mContext);
        String channel = HaloApp.getInstance().getChannel();
        map.put("version", version);
        map.put("resu", user);
        map.put("jnfj", MetaUtil.getBase64EncodedIMEI());
        map.put("channel", channel);
        map.put("updateOn", Utils.getTime(HaloApp.getInstance().getApplication()));
        map.put("type", type);

        Map<String, Object> paramsWrapper = new HashMap<>();
        if ("news".equals(type) || "download".equals(type) || "search".equals(type)) {
            paramsWrapper.put("meta", LogUtils.getMetaObject().toString());
        }
        paramsWrapper.put("topic", type);
        paramsWrapper.put("content", new JSONObject(map).toString());
        paramsWrapper.put("time", Utils.getTime(HaloApp.getInstance().getApplication()));

        LoghubUtils.log(new JSONObject(paramsWrapper), "collection", true);
    }

    public static DataCollectionManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public static void onEvent(String type, String data, boolean isUpload) {
        String id = UUID.randomUUID().toString().replace("-", "");
        DataCollectionInfo entity = new DataCollectionInfo();
        entity.setId(id);
        entity.setType(type);
        entity.setData(data);
        onEvent(entity, isUpload);
    }

    // 添加事件
    public static void onEvent(DataCollectionInfo entity, boolean isUpload) {
        DataCollectionManager.getInstance().add(entity, isUpload);
    }

    // 把事件加入列表
    public void add(DataCollectionInfo entity, boolean isUpload) {
        // 加入列表
        dao.add(entity);

        // 检查列表数目是否满足条件
        if (isUpload) {
            List<DataCollectionInfo> list = dao.getAll();
            if (list != null && list.size() >= 20) {
                try {
                    upload(list);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // todo 上传数据，不是很明白这种存数据库取出来删除再存进去再取出来再删是什么操作？也没时间改了~
    private void upload(List<DataCollectionInfo> list) throws JSONException {
        if (isUploading) {
            return;
        }
        isUploading = true;
        String version = PackageUtils.getGhVersionName();
        String user = Installation.getUUID(mContext);
        String channel = HaloApp.getInstance().getChannel();
        for (DataCollectionInfo dataCollectionInfo : list) {
            if (!"click-item".equals(dataCollectionInfo.getType())) {
                JSONObject dataObject = new JSONObject(dataCollectionInfo.getData());
                JSONArray jsonArray = dataObject.getJSONArray("data");
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    jsonObject.put("version", version);
                    jsonObject.put("resu", user);
                    jsonObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
                    jsonObject.put("channel", channel);

                    JSONObject jsonWrapper = new JSONObject();
                    jsonWrapper.put("topic", dataCollectionInfo.getType());
                    jsonWrapper.put("content", jsonObject.toString());
                    jsonWrapper.put("time", Utils.getTime(HaloApp.getInstance().getApplication()));
                    LoghubUtils.log(jsonWrapper, "collection", true);
                }
            }
            dao.delete(dataCollectionInfo.getId());
        }
        isUploading = false;
    }

    public static void upsert(Context context, String type, Map<String, Object> map) {
        map.put("createdOn", Utils.getTime(context));
        String id = UUID.randomUUID().toString().replace("-", "");
        DataCollectionInfo entity = new DataCollectionInfo();
        entity.setId(id);
        entity.setType(type);
        entity.setData(new JSONObject(map).toString());
        DataCollectionManager.getInstance().upsert(entity, type);
    }

    public void upsert(DataCollectionInfo entity, String type) {
        List<DataCollectionInfo> list = dao.findByType(type);
        if (list == null || list.isEmpty()) {
            dao.add(entity);
        } else {
            entity.setId(list.get(0).getId());
            dao.update(entity);
            if (list.size() > 1) {
                List<String> ids = new ArrayList<>();
                for (int i = 1, size = list.size(); i < size; i++) {
                    ids.add(list.get(i).getId());
                }
                dao.delete(ids);
            }
        }
    }

    // 上传数据
    public void upload() {
        statClickData();
        List<DataCollectionInfo> list = dao.getAll();
        if (list != null && !list.isEmpty()) {
            try {
                upload(list);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * 统计点击数据
     */
    public void statClickData() {
        AppExecutor.getIoExecutor().execute(() -> {
            List<DataCollectionInfo> list = dao.getClickData();
            if (list != null && !list.isEmpty()) {
                List<String> ids = new ArrayList<>();
                List<Object> data = new ArrayList<>();
                try {
                    DataCollectionInfo dataCollectionEntity;
                    for (int i = 0, size = list.size(); i < size; i++) {
                        dataCollectionEntity = list.get(i);
                        ids.add(dataCollectionEntity.getId());
                        data.add(new JSONObject(dataCollectionEntity.getData()));
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                Map<String, Object> map = new HashMap<>();
                map.put("data", data);
                onEvent(mContext, "click", map);
                dao.delete(ids);
            }
        });
    }

    public static void onEvent(Context context, String type, Map<String, Object> map) {
        AppExecutor.getIoExecutor().execute(() -> {
            map.put("createdOn", Utils.getTime(context));
            if ("news".equals(type) || "download".equals(type) || "search".equals(type)) {
                DataCollectionManager.getInstance().realTimeUpload(type, map);
                return;
            }
            onEvent(type, new JSONObject(map).toString(), true);
        });
    }

    private static class SingletonHolder {
        private static final DataCollectionManager INSTANCE = new DataCollectionManager();
    }
}
