package com.imofan.android.basic;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * 用户行为事件封装类
 */
public class MFStatEvent {
    private final static String LOG_TAG = Mofang.LOG_TAG + "_MFEvent";

    final static String TABLE = "event";  //用户行为数据表表名
    final static String FIELD_ID = "id";
    final static String FIELD_DATE = "date";
    final static String FIELD_HOUR = "hour";
    final static String FIELD_EVENT = "event";
    final static String FIELD_VALUE = "value";
    final static String FIELD_COUNT = "count";
    final static String FIELD_EXIT = "exit";
    final static String FIELD_DURATION = "duration";
    final static String FIELD_FIRST = "first";
    final static String FIELD_TIME = "time";
    final static String FIELD_SEND = "send";

    final static String EVENT_INSTALL = "install";      //安装事件
    final static String EVENT_UPGRADE = "upgrade";      //升级事件
    final static String EVENT_OPEN = "open";             //启动应用事件
    final static String EVENT_COLSE = "close";          //关闭应用事件
    final static String EVENT_RETURN_USER = "return";  //回头用户事件
    final static String EVENT_DEVELOPER = "developer"; //开发者自定义事件
    final static String EVENT_UPDATE = "update";        //设备信息更新事件
    final static String EVENT_ACCESS_PATH = "path";     //访问路径数据
    final static String EVENT_ACCESS_NODE = "node";     //访问节点数据
    public final static String EVENT_NOTIFICATION_RECEIVE = "notification_receive";             //推送事件
    public final static String EVENT_NOTIFICATION_OPEN = "notification_open";//推送消息显示事件
    final static String EVENT_CRASH = "crash";           //Crash异常

    final static String CREATE_SQL =
            "CREATE TABLE IF NOT EXISTS " + TABLE + " (" +
                FIELD_ID + " INTEGER PRIMARY KEY, " +
                FIELD_DATE + " INTEGER NOT NULL, " +
                FIELD_HOUR + " INTEGER NOT NULL, " +
                FIELD_EVENT + " TEXT NOT NULL, " +
                FIELD_VALUE + " TEXT, " +
                FIELD_COUNT + " INTEGER DEFAULT 1, " +
                FIELD_EXIT + " INTEGER DEFAULT 0, " +
                FIELD_DURATION + " INTEGER DEFAULT 0, " +
                FIELD_FIRST + " INTEGER DEFAULT 0, " +
                FIELD_TIME + " NUMERIC NOT NULL, " +
                FIELD_SEND + " INTEGER DEFAULT 0);";

    private int id;
    private int date;                                   //事件发生的日期，由年月日组成的8位数字，比如：20120413，表示2012年4月13日
    private int hour;                                   //事件发生的小时，取值范围为0-23，比如：9，表示早上9点
    private String event;                                //事件名称，比如：open，表示启动事件
    private String value;                                //事件值，比如自定义标签的标签值：read:article
    private int count = 0;                              //事件触发次数
    private int exit = 0;                               //访问节点跳出次数
    private long duration = 0;                          //事件持续时长，单位：秒
    private boolean first = false;                     //是否该日第一次触发该事件，取值为：0、1
    private long time = System.currentTimeMillis();     //事件发生时间
    private boolean send = false;                      //是否已经发送给服务端

    //自动解析数据库数据为Event对象
    static MFStatEvent parse(Cursor cur) {
        MFStatEvent event = new MFStatEvent();
        if(cur.getColumnIndex(FIELD_ID) > -1) {
            event.setId(cur.getInt(cur.getColumnIndex(FIELD_ID)));
        }
        if(cur.getColumnIndex(FIELD_DATE) > -1) {
            event.setDate(cur.getInt(cur.getColumnIndex(FIELD_DATE)));
        }
        if(cur.getColumnIndex(FIELD_HOUR) > -1) {
            event.setHour(cur.getInt(cur.getColumnIndex(FIELD_HOUR)));
        }
        if(cur.getColumnIndex(FIELD_EVENT) > -1) {
            event.setEvent(cur.getString(cur.getColumnIndex(FIELD_EVENT)));
        }
        if(cur.getColumnIndex(FIELD_VALUE) > -1) {
            event.setValue(cur.getString(cur.getColumnIndex(FIELD_VALUE)));
        }
        if(cur.getColumnIndex(FIELD_COUNT) > -1) {
            event.setCount(cur.getInt(cur.getColumnIndex(FIELD_COUNT)));
        }
        if(cur.getColumnIndex(FIELD_EXIT) > -1) {
            event.setExit(cur.getInt(cur.getColumnIndex(FIELD_EXIT)));
        }
        if(cur.getColumnIndex(FIELD_DURATION) > -1) {
            event.setDuration(cur.getLong(cur.getColumnIndex(FIELD_DURATION)));
        }
        if(cur.getColumnIndex(FIELD_FIRST) > -1) {
            event.setFirst(cur.getInt(cur.getColumnIndex(FIELD_FIRST)) == 1);
        }
        if(cur.getColumnIndex(FIELD_TIME) > -1) {
            event.setTime(cur.getLong(cur.getColumnIndex(FIELD_TIME)));
        }
        if(cur.getColumnIndex(FIELD_SEND) > -1) {
            event.setSend(cur.getInt(cur.getColumnIndex(FIELD_SEND)) == 1);
        }
        return event;
    }

    //将Event对象持久化到数据库中
    //因为事件不存在update的可能，故该方法暂只考虑insert
    private void persist(MFDatabaseManager dbManager) {
        SQLiteDatabase database = dbManager.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(FIELD_DATE, this.getDate());
        cv.put(FIELD_HOUR, this.getHour());
        cv.put(FIELD_EVENT, this.getEvent());
        if(this.getValue() != null) {
            cv.put(FIELD_VALUE, this.getValue());
        }
        cv.put(FIELD_EXIT, this.getExit());
        cv.put(FIELD_COUNT, this.getCount());
        cv.put(FIELD_DURATION, this.getDuration());
        cv.put(FIELD_FIRST, this.isFirst() ? 1 : 0);
        cv.put(FIELD_TIME, this.getTime());
        cv.put(FIELD_SEND, this.isSend() ? 1 : 0);
        database.insert(TABLE, null, cv);
    }

    //获取某个事件某天的所有数据
    static List<MFStatEvent> getEvents(MFDatabaseManager dbManager, String event, String value, int date, boolean send) {
        String where = " where " + MFStatEvent.FIELD_SEND + "=?";
        List<String> paramList = new ArrayList<String>();
        if(send) {
            paramList.add("1");
        } else {
            paramList.add("0");
        }
        if(event != null && event.trim().length() > 0) {
            where += " and " +  MFStatEvent.FIELD_EVENT + "=?";
            paramList.add(event);
        }
        if(value != null && value.trim().length() > 0) {
            if(where.length() > 0) {
                where += " and " + MFStatEvent.FIELD_VALUE + "=?";
            } else {
                where = MFStatEvent.FIELD_VALUE + "=?";
            }
            paramList.add(value);
        }
        if(date > 0) {
            if(where.length() > 0) {
                where += " and " + MFStatEvent.FIELD_DATE + "=?";
            } else {
                where = MFStatEvent.FIELD_DATE + "=?";
            }
            paramList.add(Integer.toString(date));
        }
        String[] params = null;
        params = new String[paramList.size()];
        for(int i=0; i<paramList.size(); i++) {
            params[i] = paramList.get(i);
        }

        SQLiteDatabase db = dbManager.getReadableDatabase();
        Cursor cur = null;
        try {
            cur = db.rawQuery("select * from " + MFStatEvent.TABLE + where
                    + " order by " + MFStatEvent.FIELD_TIME, params);
            if(cur.getCount() > 0) {
                List<MFStatEvent> events = new ArrayList<MFStatEvent>(cur.getCount());
                while(cur.moveToNext()) {
                    events.add(MFStatEvent.parse(cur));
                }
                return events;
            }
        } finally {
            if(cur != null) {
                cur.close();
            }
        }
        return null;
    }

    static int[] getEventDates(MFDatabaseManager dbManager) {
        int[] dates = null;
        SQLiteDatabase db = dbManager.getReadableDatabase();
        Cursor cur = null;
        try {
            cur = db.rawQuery("select " + FIELD_DATE + " from " + MFStatEvent.TABLE
                    + " where " + FIELD_SEND + "=? and " + FIELD_EVENT + "<>?"
                    + " order by " + FIELD_DATE, new String[]{"0", EVENT_UPDATE});
            if(cur.getCount() > 0) {
                List<Integer> dateList = new ArrayList<Integer>();
                int lastDate = 0;
                while(cur.moveToNext()) {
                    int date = cur.getInt(cur.getColumnIndex(FIELD_DATE));
                    if(date > 0 && date != lastDate) {
                        dateList.add(date);
                        lastDate = date;
                    }
                }
                if(dateList.size() > 0) {
                    dates = new int[dateList.size()];
                    for(int i=0; i<dateList.size(); i++) {
                        dates[i] = dateList.get(i);
                    }
                }
            }
        } finally {
            if(cur != null) {
                cur.close();
            }
        }
        return dates;
    }

    //添加事件数据
    static void addEvent(MFDatabaseManager dbManager, String event, int date,
                         int hour, String value, int count, int exit, long duration, boolean first, long time) {
        //对推送接收和打开数进行除重处理
//        if(event == EVENT_NOTIFICATION_RECEIVE || event == EVENT_NOTIFICATION_OPEN) {
//            SQLiteDatabase db = dbManager.getReadableDatabase();
//            Cursor cur = null;
//            try {
//                cur = db.rawQuery("select 1 from " + MFStatEvent.TABLE
//                        + " where " + FIELD_EVENT + "=? and " + FIELD_VALUE + "=?",
//                        new String[]{event, value});
//                if(cur.getCount() > 0) {
//                    return;
//                }
//            } finally {
//                if(cur != null) {
//                    cur.close();
//                }
//            }
//        }

        MFStatEvent ev = new MFStatEvent();
        ev.setEvent(event);
        ev.setDate(date);
        ev.setHour(hour);
        ev.setValue(value);
        ev.setCount(count);
        ev.setExit(exit);
        ev.setDuration(duration);
        ev.setFirst(first);
        if(time > 0) {
            ev.setTime(time);
        }

        try {
            ev.persist(dbManager);
            if(Mofang.DEBUG) {
                Log.d(LOG_TAG, "[addEvent]" + ev);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //清除访问路径和节点的数据
    static void clearAccessPath(MFDatabaseManager dbManager) {
        SQLiteDatabase database = dbManager.getWritableDatabase();
        database.delete(TABLE, FIELD_EVENT + "=?", new String[]{EVENT_ACCESS_PATH});
        database.delete(TABLE, FIELD_EVENT + "=?", new String[]{EVENT_ACCESS_NODE});

        if(Mofang.DEBUG) {
        	LogUtils.writeLog("清除访问路径和节点的数据");
            Log.d(LOG_TAG, "[clearAccessPath]");
        }
    }

    //清除历史事件数据
    static void clearHistoryEvents(MFDatabaseManager dbManager, int date) {
        SQLiteDatabase database = dbManager.getWritableDatabase();
        database.delete(TABLE, FIELD_SEND + "=? and " + FIELD_DATE + "<?",
                new String[]{"1", Integer.toString(date)});

        if(Mofang.DEBUG) {
            Log.d(LOG_TAG, "[clearHistoryEvents]");
            LogUtils.writeLog("清除历史事件数据");
        }
    }

    //添加事件数据
    static void addEvent(MFDatabaseManager dbManager, String event, int date,
                         int hour, String value, int count, long duration, boolean first, long time) {
        addEvent(dbManager, event, date, hour, value, count, 0, duration, first, time);
    }

    //添加事件数据
    public static void addEvent(MFDatabaseManager dbManager, String event, int date, int hour, String value) {
        addEvent(dbManager, event, date, hour, value, 1, 0, false, 0);
    }

    //标记事件已发送
    static void signSentEvent(MFDatabaseManager dbManager, List<Integer> idList) {
        SQLiteDatabase db = dbManager.getWritableDatabase();
        
        LogUtils.writeLog("标记事件 : "+idList);
        
        for(int id : idList) {
            ContentValues cv = new ContentValues();
            cv.put(MFStatEvent.FIELD_SEND, "1");
            db.update(MFStatEvent.TABLE, cv, "id=?", new String[]{Integer.toString(id)});
        }

        if(Mofang.DEBUG) {
            Log.d(LOG_TAG, "[signSentEvent]");
            LogUtils.writeLog("标记事件结束");
        }
    }

    @Override
    public String toString() {
        return "{id=" + id + ", event=" + event + ", date=" + date + ", hour=" + hour
                + ", value=" + value + ", count=" + count + ", exit=" + exit + ", duration=" + duration
                + ", first=" + first + ", time=" + time + ", send=" + send + "}";
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getDate() {
        return date;
    }

    public void setDate(int date) {
        this.date = date;
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }

    public String getEvent() {
        return event;
    }

    public void setEvent(String event) {
        this.event = event;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        if(count > 0) {
            this.count = count;
        }
    }

    public int getExit() {
        return exit;
    }

    public void setExit(int exit) {
        if(exit > 0) {
            this.exit = exit;
        }
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        if(duration > 0) {
            this.duration = duration;
        }
    }

    public boolean isFirst() {
        return first;
    }

    public void setFirst(boolean first) {
        this.first = first;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public boolean isSend() {
        return send;
    }

    public void setSend(boolean send) {
        this.send = send;
    }
}
