import 'dart:async';
import 'dart:io' as io;
import 'UnitModel.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'Prefs.dart';
import '../main.dart';

class DBHelper {
  DBHelper._();

  static final DBHelper database = DBHelper._();
  static Database _db;

  Future<Database> get db async {
    if (_db != null) return _db;
    _db = await initDb();
    return _db;
  }

  initDb() async {
    io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, "UnitStocking.db");
    var theDb = await openDatabase(path, version: 1,onCreate: await _onCreate);
    return theDb;
  }

  closeDb() async {
    final database = await db;
    await database.close();
    _db = null;
  }

  _onCreate(Database db, int version) async {
    io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, "UnitStocking.db");
    io.File file = io.File(path);
    print('Database created, ${file.lengthSync()}');
    var res = await db.query(tableName.values,where: "${columnName.name} = ?",whereArgs: [keyClass.stock_id]);
    valueTab value = valueTab.fromJson(res.first);
    await prefs.setString(keyClass.stock_id, value.value);
  }

  getCount(mesin) async {
    final database = await db;
    var res =
    await database.rawQuery("SELECT COUNT(*) as count FROM ${tableName.blob} where ${columnName.mesin} = '$mesin'");
    return res.isNotEmpty ? Count.fromJson(res.first).count : 0;
  }

  getUnitdetailMaster(id) async{
    try{
      final database = await db;
      var res = await database.rawQuery("SELECT * FROM '${tableName.master}' WHERE ${columnName.id} = $id");
      return res.isNotEmpty ? Unit.fromJson(res.first) : null;
    }
    catch(e){
      print(e);
      return null;
    }
  }

//  Future<List<Unit>> getAllUnits() async {
//    final database = await db;
//    var res = await database.query("${tableName.master}");
////    var res = await database.rawQuery("SELECT ${columnName.tipe} from ${tableName.}");
////    var res = await database.rawQuery("SELECT b.${columnName.id}, b.${columnName.mesin}, b.${columnName.tipe}, b.${columnName.warna}, IFNULL((SELECT ${columnName.timestamp} from ${tableName.unit} where ${columnName.mesin} = b.${columnName.mesin}),'-') ${columnName.timestamp}, (SELECT ${columnName.id} from ${tableName.unit} where ${columnName.mesin} = b.${columnName.mesin}) ${columnName.mesin_id} from ${tableName.master} b");
//    List<Unit> list =
//    res.isNotEmpty ? res.map((c) => Unit.fromJson(c)).toList() : [];
//    return list;
//  }

  Future<List<Unit>> getAllUnits({inserted=false}) async {
    final database = await db;
    var res = await database.query("${tableName.master}",where: (inserted)?"${columnName.flag} = 'TRUE'":null,orderBy: "CASE WHEN ${columnName.flag} = 'FALSE' THEN 0 ELSE 1 END,  ${columnName.state} desc");
//    var res = await database.rawQuery("SELECT ${columnName.id}, ${columnName.mesin}, ${columnName.tipe}, ${columnName.state}, ${columnName.warna}, ${columnName.rangka},${columnName.kode},${columnName.flag}, ${columnName.timestamp} from ${tableName.master}  ORDER BY CASE WHEN ${columnName.flag} = 'FALSE' THEN 0 ELSE 1 END,  ${columnName.state} desc");
    List<Unit> list =
    res.isNotEmpty ? res.map((c) => Unit.fromJson(c)).toList() : [];
    return list;
  }

  Future<List<Unit>> searchAllUnits(String query,{inserted:false}) async {
    print("${(inserted)?"${columnName.flag} = 'TRUE' AND ":''} REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%'");
    final database = await db;
    try{
      var res = await database.query(tableName.master,where: "${(inserted)?"${columnName.flag} = 'TRUE' AND ":''} (REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%')",orderBy: "CASE WHEN ${columnName.flag} = 'FALSE' THEN 0 ELSE 1 END, ${columnName.state} desc");
//      var res = await database.rawQuery(
//          "select * from (SELECT ${columnName.id}, ${columnName.state}, ${columnName.rangka}, ${columnName.mesin}, ${columnName.tipe}, ${columnName.warna},  ${columnName.timestamp}, ${columnName.mesin} from ${tableName.master} ) where REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%' ORDER BY CASE WHEN ${columnName.flag} = 'FALSE' THEN 0 ELSE 1 END, ${columnName.state} desc");
      List<Unit> list =
      res.isNotEmpty ? res.map((c) => Unit.fromJson(c)).toList() : [];
      return list;
    }
    catch(e){
      print(e);
      return [];
    }

  }

//  Future<List<insertUnit>> getAllInsertUnits() async {
//    final database = await db;
////    var res = await database.query("${tableName.unit}");
//    var res = await database.rawQuery("SELECT a.${columnName.id},a.${columnName.mesin},b.${columnName.rangka},b.${columnName.tipe},b.${columnName.warna}, a.${columnName.timestamp}, b.${columnName.state} from ${tableName.unit} a, ${tableName.master} b where a.${columnName.mesin} = b.${columnName.mesin}");
//    List<insertUnit> list =
//    res.isNotEmpty ? res.map((c) => insertUnit.fromJson(c)).toList() : [];
//    return list;
//  }

//  Future<List<blobImage>> getAllBlobImage(mesin) async {
//    final database = await db;
////    var res = await database.query("${tableName.blob}");
//    var res = await database.query("${tableName.blob}",where: "${columnName.mesin} = ?",whereArgs: [mesin]);
////    print([mesin_id,res]);
//
//    List<blobImage> list =
//    res.isNotEmpty ? res.map((c) => blobImage.fromJson(c)).toList() : [];
//    return list;
//  }

  getBlobUnits(mesin) async{
    try{
      final database = await db;
      var res = await database.query("${tableName.blob}" ,where: "${columnName.mesin} = ?", whereArgs: [mesin]);
      List<blobImage> list =
      res.isNotEmpty ? res.map((c) => blobImage.fromJson(c)).toList() : [];
      return list;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  insertUpdateBlob(blobImage blob) async{
    return (blob.blob_id==null)?newInsertBlob(blob):updateBlob(blob);
  }

  deleteBlob(blob_id) async {
    final database = await db;
    try{
      await database.delete("${tableName.blob}", where: "${columnName.blob_id} = ?", whereArgs: [blob_id]);
      return true;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  updateUnit(Unit unitUpdate) async{
    try{
      final database = await db;
      var res = await database.update("${tableName.master}", unitUpdate.toJson(),
          where: "${columnName.id} = ?", whereArgs: [unitUpdate.id]);
      print('Row Updated');
      return res;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  updateBlob(blobImage blobUpdate) async{
    try{
      final database = await db;
      var res = await database.update("${tableName.blob}", blobUpdate.toJson(),
          where: "${columnName.blob_id} = ?", whereArgs: [blobUpdate.blob_id]);
      print('Row Updated');
      return res;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  newInsertBlob(blobImage newBlob) async {
    final database = await db;
    try{
      var res = await database.rawInsert("Insert into ${tableName.blob}(${columnName.blob_file},${columnName.mesin},${columnName.lat},${columnName.long},${columnName.jenis})VALUES(?,?,?,?,?)", [
        newBlob.blob_file,
        newBlob.mesin,
        newBlob.lat,
        newBlob.long,
        newBlob.jenis
      ]);
      print('Image Inserted');
      return res;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  getBlobImage(mesin) async{
    final database = await db;
    var res = await database.query("${tableName.blob}",where: "${columnName.mesin} = ? AND ${columnName.no_urut} = ?",whereArgs: [mesin,'1']);
    return res.isNotEmpty ? blobImage.fromJson(res.first) : null;
  }

//  Future<List<insertUnit>> searchAllInsertUnits(String query) async {
//    final database = await db;
//    var res = await database.rawQuery(
//        "select * from (SELECT a.${columnName.id},a.${columnName.mesin},b.${columnName.tipe},b.${columnName.warna}, a.${columnName.timestamp}, b.${columnName.state}, b.${columnName.rangka} from ${tableName.unit} a, ${tableName.master} b where a.${columnName.mesin} = b.${columnName.mesin}) where REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.warna} like '%$query%' or ${columnName.tipe} like '%$query%'");
//    List<insertUnit> list =
//    res.isNotEmpty ? res.map((c) => insertUnit.fromJson(c)).toList() : [];
//    return list;
//  }
//
//  updateInsertUnit(insertUnit newPart) async {
//    try{
//      final database = await db;
////      var res = await database.update("${tableName.unit}", newPart.toJson(),
////          where: "${columnName.id} = ?", whereArgs: [newPart.id]);
//      var res = await database.rawQuery("Update ${tableName.unit} SET ${columnName.id} = ${newPart.id}, ${columnName.mesin} = '${newPart.mesin}' WHERE ${columnName.id} = ${newPart.id}");
//      print('Row Updated');
//      return res;
//    }
//    catch(e){
//      print(e);
//      return null;
//    }
//  }

  Future<List<jenisDrop>> getAllJenis() async {
    try{
      final database = await db;
      var res = await database.query("${tableName.jenis}");
//      var res = (id==null)?await database.query("${tableName.jenis}") :await database.rawQuery("select a.${columnName.value}, b.${columnName.jenis}  from ${tableName.jenis} a, ${tableName.blob} b where a.${columnName.value} <> b.${columnName.jenis} AND b.${columnName.mesin_id} = $id");
//      print(res);
      List<jenisDrop> list =
      res.isNotEmpty ? res.map((c) => jenisDrop.fromJson(c)).toList() : [];
      return list;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  getValue(value)async{
    try{
      final database = await db;
      var res = await database.query(tableName.values,where: "${columnName.name} = ?",whereArgs: [value]);
      return res.isEmpty?null:valueTab.fromJson(res.first);
    }
    catch(e){
      return  null;
    }
  }

  insertUpdateValue(valueTab newValue)async{
    try{
      final database = await db;
      var res = await database.rawQuery("Select Count(*) as count  from ${tableName.values} where ${columnName.name} = '${newValue.name}'");
      int count = res.isNotEmpty ? Count.fromJson(res.first).count : 0;
      return (count==0)?addNewValue(newValue):updateValue(newValue);
    }
    catch(e){
      print(e);
      return null;
    }
  }

  updateValue(valueTab newValue) async {
    try{
      final database = await db;
      var res = await database.update("${tableName.values}", newValue.toJson(),
          where: "${columnName.name} = ?", whereArgs: [newValue.name]);
      print('Row Updated');
      return res;
    }
    catch(e){
      print(e);
      return null;
    }
  }

  addNewValue(valueTab newValue) async {
    final database = await db;
    try{
      var res = await database.rawInsert("Insert into ${tableName.values}(${columnName.name},${columnName.value})VALUES(?,?)", [
        newValue.name,
        newValue.value
      ]);
      print('Row Inserted');
      return res;
    }
    catch(e){
      print(e);
      return null;
    }
  }

//  deleteInsertUnit(String id) async {
//    final database = await db;
//    try{
//      await database.delete("${tableName.unit}", where: "${columnName.id} = ?", whereArgs: [id]);
//      return true;
//    }
//    catch(e){
//      print(e);
//      return null;
//    }
//  }

  deleteAll() async {
    final database = await db;
    try{
      await database.rawQuery("DROP TABLE IF EXISTS ${tableName.blob}");
//      await database.rawQuery("DROP TABLE IF EXISTS ${tableName.unit}");
      await database.rawQuery("DROP TABLE IF EXISTS ${tableName.master}");
      return true;
    }
    catch(e){
      print(e);
      return null;
    }
  }

}
