library qm_tj;

import 'dart:convert';

import 'src/db.dart';
import 'src/http.dart';
import 'package:crypto/crypto.dart' as crypto;

class QMTJ {
  static DB _db;
  static Http _http;
  static String _appStartUpId;

  static Future<bool> ready;

  static bool isDebug = false;

  static void debug() {
    isDebug = true;
  }

  static init() async {
    _http = Http(scheme: "http", host: "8.135.58.206", port: 8802);
    _appStartUpId = _md5(_getDateNow().toString());
    ready = new Future<bool>(() async {
      _db = new DB();
      await _db.init();
      return true;
    });
    await ready;
    uploadPageTj();
  }

  /// APP 启动
  static void appStart({int source, Map<String, dynamic> extras}) async {
    int type = 1;
    int disappearTime = 0;
    int appearTime = _getDateNow();
    String id = _appStartUpId;
    Map<String, dynamic> map = {
      "id": id,
      "type": type,
      "source": source,
      "disappear_time": disappearTime,
      "appear_time": appearTime,
      "extras": json.encode(extras),
    };
    await ready;
    log("appStart", map);
    await _db.db.insert("app_tj", map);
  }

  /// APP 可见
  static void appAppear({int source, Map<String, dynamic> extras}) async {
    // APP进入前台,重新生成启动id
    _appStartUpId = _md5(_getDateNow().toString());

    int type = 2;
    int disappearTime = 0;
    int appearTime = _getDateNow();
    String id = _appStartUpId;
    Map<String, dynamic> map = {
      "id": id,
      "type": type,
      "source": source,
      "disappear_time": disappearTime,
      "appear_time": appearTime,
      "extras": json.encode(extras),
    };
    await ready;
    log("appAppear", map);
    await _db.db.insert("app_tj", map);
  }

  /// APP 不可见
  static void appDisappear() async {
    int disappearTime = _getDateNow();
    Map<String, dynamic> map = {
      "id": _appStartUpId,
      "disappear_time": disappearTime,
    };
    await ready;
    log("appDisappear", map);
    _db.db.update("app_tj", {"disappear_time": disappearTime},
        where: "id = ? and disappear_time = 0", whereArgs: [_appStartUpId]);
  }

  /// PAGE 可见
  static void pageAppear(
      {int source,
      String pageId,
      String lastPageId,
      Map<String, dynamic> extras}) async {
    String extrasStr = json.encode(extras);
    String id = _md5("${pageId}_${lastPageId}_$extrasStr");
    int disappearTime = 0;
    int appearTime = _getDateNow();
    Map<String, dynamic> map = {
      "id": id,
      "source": source,
      "page_id": pageId,
      "last_page_id": lastPageId,
      "appear_time": appearTime,
      "disappear_time": disappearTime,
      "extras": extrasStr,
    };
    await ready;
    log("pageAppear", map);
    await _db.db.insert("page_tj", map);
  }

  /// PAGE 不可见
  static void pageDisappear(
      {String pageId, String lastPageId, Map<String, dynamic> extras}) async {
    String extrasStr = json.encode(extras);
    String id = _md5("${pageId}_${lastPageId}_$extrasStr");
    int disappearTime = _getDateNow();
    Map<String, dynamic> map = {
      "id": id,
      "page_id": pageId,
      "last_page_id": lastPageId,
      "disappear_time": disappearTime,
      "extras": extrasStr,
    };
    await ready;
    log("pageDisappear", map);
    await _db.db.update(
        "page_tj",
        {
          "disappear_time": disappearTime,
        },
        where: "id = ?  and disappear_time = 0",
        whereArgs: [id]);
  }

  /// 点击
  /// [pageId] 页面id
  /// [clickId] 点击id
  /// [extras] 点击参数
  static void tap(
      {int source,
      String pageId,
      String clickId,
      Map<String, dynamic> extras}) async {
    int clickTime = _getDateNow();
    String extrasStr = json.encode(extras);
    String id = _md5("${pageId}_${clickId}_${extrasStr}_${clickTime}");
    Map<String, dynamic> map = {
      "id": id,
      "source": source,
      "page_id": pageId,
      "click_id": clickId,
      "click_time": clickTime,
      "extras": extrasStr,
    };
    await ready;
    log("tap", map);
    await _db.db.insert("tap_tj", map);
  }

  /// 曝光
  /// [pageId] 页面id
  /// [exposureId] 曝光id
  /// [extras] 曝光参数
  static void exposure(
      {int source,
      String pageId,
      String exposureId,
      Map<String, dynamic> extras}) async {
    int exposureTime = _getDateNow();
    String extrasStr = json.encode(extras);
    String id = _md5("${pageId}_${exposureId}_${extrasStr}_${exposureTime}");
    Map<String, dynamic> map = {
      "id": id,
      "source": source,
      "page_id": pageId,
      "exposure_id": exposureId,
      "exposure_time": exposureTime,
      "extras": extrasStr,
    };
    await ready;
    log("exposure", map);
    await _db.db.insert("exposure_tj", map);
  }

  // 上传页面统计
  static void uploadPageTj() async {
    List<Map> list = await _db.db.query("page_tj", limit: 100, offset: 0);
    if (list.length == 0) {
      return;
    }
    List<String> ids = [];
    list = list.map((e) {
      var item = {
        "app_version": '0.0.1',
        "app_channel": "APP渠道",
        "devices_id": '3A26610FFE43D5838DDE7A40BA2E3E2C',
        "inter": '4G',
        "source": e['source'],
        "page_id": e['page_id'],
        "last_page_id": e['last_page_id'],
        "come_time": e['appear_time'],
        "out_time": e['disappear_time'],
        "extras": json.decode(e['extras'])
      };
      ids.add(e['id']);
      Map project = {
        "event_name": "page_scan",
        "app": "xx",
        "event_info": item
      };
      return project;
    }).toList();

    _http.post("/collection", {"project": json.encode(list)}).then(
        (value) async {
      if (isDebug) {
        log("upload_page_tj",  Map<String,dynamic>.from(value));
      }
      if (value != null && value['code'] == 200) {
        int result = await _db.db
            .rawDelete("delete from page_tj where id in('${ids.join("','")}')");
        log("clear_page_tj", Map<String, dynamic>.from(
            {"olength": list.length, "length": result}));
      }
      uploadPageTj();
    });
  }

  /// 获取当前时间戳,单位:秒
  static int _getDateNow() {
    int now = (DateTime.now().millisecondsSinceEpoch / 1000).floor();
    return now;
  }

  // md5编码
  static String _md5(String data) {
    var bytes = utf8.encode(data);
    var digest = crypto.md5.convert(bytes);
    return digest.toString();
  }

  static void log(String type, Map<String, dynamic> map) {
    if (!isDebug) {
      return;
    }
    print("$type=======================s===========================$type");
    print(map);
    print("$type=======================e===========================$type");
  }
}