package kr.co.icontrols.ilp300_700.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.os.Environment;
import android.util.Log;

import java.io.File;

import kr.co.icontrols.ilp300_700.global.Configure;

public class DBManager {

    String TAG = "DBManager";

    boolean bLOG = true;   // true, false
    boolean bLOG_DEBUG = false;   // true, false
    boolean bLOG_INFO = true;   // true, false
    Context mContext;
    SQLiteDatabase mSQLiteDatabase;
    String DATABASE_LOCATION = "/sdcard/BESTIN/DATABASE";
    String DATABASE_FILENAME = "";
    String DATABASE_FULLPATH = "";
    CursorFactory mCursorFactory = null;
    File mDatabaseFile;
    int nVersion = 1;
    public DBManager(Context context, String filename) {
        mContext = context;
        DATABASE_FILENAME = filename;
        DATABASE_FULLPATH = DATABASE_LOCATION + "/" + DATABASE_FILENAME;
        mDatabaseFile = new File(DATABASE_FULLPATH);
    }

    private void LOG(String log) {
        if (bLOG) Log.v(TAG, log);
    }

    private void LOG_DEBUG(String log) {
        if (bLOG_DEBUG) Log.d(TAG, log);
    }

    private void LOG_INFO(String log) {
        if (bLOG_INFO) Log.i(TAG, log);
    }

    public boolean initDatabase() {
        try {
            LOG("[initDatabase] ===== START =====");
            return openORcreateDatabase();
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initDatabase()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean resetDatabase() {
        try {
            LOG("[resetDatabase] ===== START =====");
            if (deleteDBFile()) {
                return openORcreateDatabase();
            } else return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] resetDatabase()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean closeDatabase() {
        try {
            mSQLiteDatabase.close();
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] closeDatabase()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean isDBFileExist() {
        try {
            LOG("[isDBFileExist] ===== START =====");

            if (mDatabaseFile.exists()) return true;
            else return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] isDBFileExist()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean deleteDBFile() {
        try {
            LOG("[deleteDBFile] ===== START =====");
            if (mDatabaseFile.exists()) {
                if (mDatabaseFile.delete()) {
                    LOG("[deleteDBFile] Succeeded deleting a database file!! [1]");
                    return true;
                } else {
                    LOG("[deleteDBFile] Failed to delete a database file!! [1]");
                    if (mDatabaseFile.delete()) {
                        LOG("[createDB] Succeeded deleting a database file!! [2]");
                        return true;
                    } else {
                        LOG("[deleteDBFile] Failed to delete a database file!! [2]");
                        return false;
                    }
                }
            } else {
                LOG("[deleteDBFile] There is no file to delete [" + mDatabaseFile.getPath() + "]");
                return true;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] deleteDBFile()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean openORcreateDatabase() {
        try {
            LOG("[openORcreateDatabase] ===== START =====");

            mSQLiteDatabase = mContext.openOrCreateDatabase(DATABASE_FULLPATH, SQLiteDatabase.OPEN_READWRITE, null);

            if (mSQLiteDatabase != null) {
                mSQLiteDatabase.setVersion(nVersion);
                return true;
            } else {
                return false;
            }

        } catch (Exception e) {
            Log.e(TAG, "[Exception] createDB()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean createTable(String table, String[] values) {
        try {
            LOG("[createTable] table = " + table);
            if (isTableExist(table)) {
                LOG("[createTable] Already exist [" + table + "]");
                return false;
            }
            String DBValues = "";
            if (values != null) {
                for (int i = 0; i < values.length; i++) {
                    LOG("[createTable] valus[" + i + "] = " + values[i]);
                    if (i == values.length - 1) DBValues += values[i] + " text);";
                    else DBValues += values[i] + " text, ";
                }
            }

            String DBQuiry = "create table " + table + "(ID integer PRIMARY KEY autoincrement, " + DBValues + "TIMESTAMP DATE DEFAULT (datetime('now','localtime')));";
            LOG("[createTable] DBQuiry : " + DBQuiry);
            mSQLiteDatabase.execSQL(DBQuiry);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] createTable(tablename, valus)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean resetTable(String table) {
        try {
            LOG("[resetTable] table = " + table);
            if (isTableExist(table)) {
                String DBQuiry = "DELETE FROM " + table + ";";
                LOG("[resetTable] DBQuiry : " + DBQuiry);
                mSQLiteDatabase.execSQL(DBQuiry);
                LOG("[resetTable] Succeeded resetting a database table!! [" + table + "]");
                return true;
            } else {
                LOG("[resetTable] Target table does not exist!! [" + table + "]");
                return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] resetTable(table)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean deleteTable(String table) {
        try {
            LOG("[deleteTable] table = " + table);
            if (isTableExist(table)) {
                String DBQuiry = "drop table " + table + ";";
                LOG("[deleteTable] DBQuiry :" + DBQuiry);
                mSQLiteDatabase.execSQL(DBQuiry);
                LOG("[deleteTable] Succeeded deleting a database table!! [" + table + "]");
                return true;
            } else {
                LOG("[deleteTable] Target table does not exist!! [" + table + "]");
                return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] deleteTable(table)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean isTableExist(String table) {
        try {
            LOG("[isTableExist] table = " + table);
            String DBQuiry = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='" + table + "'";
            LOG("[isTableExist] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
            int nResult = 0;
            if (cursor.moveToNext()) nResult = cursor.getInt(0);

            if (nResult == 1) return true;
            else return false;

        } catch (Exception e) {
            Log.e(TAG, "[Exception] isTableExist(table)");
            e.printStackTrace();
            return false;
        }
    }

    public int isKeyExist(String table, String key) {
        try {
            // Key값으로 검색하여 나온 레코드의 개수를 반환한다.
            LOG_DEBUG("[isKeyExist] table [" + table + "], key [" + key + "]");
            String DBQuiry = "select * from " + table + " where KEY=\"" + key + "\";";
            LOG_DEBUG("[isKeyExist] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
            int nRecCnt = cursor.getCount();
            LOG_DEBUG("[isKeyExist] nRecCnt : " + nRecCnt);
            cursor.close();
            return nRecCnt;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getDataAll(table, key)");
            e.printStackTrace();
            return 0;
        }
    }

    public boolean setData(String table, String key, String value) {
        try {
            LOG_DEBUG("[setData] table [" + table + "], key [" + key + "], value [" + value + "]");
            ContentValues values = new ContentValues();
            values.put("KEY", key);
            values.put("VALUE", value);

            String SQLkey = "KEY = '" + key + "'";
            int nResultCnt = mSQLiteDatabase.update(table, values, SQLkey, null);
//            DEBUG("[setData] nResultCnt = " + nResultCnt);
            if (nResultCnt == 1) {
                // 레코드 업데이트 완료
                LOG_DEBUG("[setData] Update OK!!");
                return true;
            } else if (nResultCnt == 0) {
                // 테이블에 레코드 키정보가 없는 경우, 새로 생성한다.
                if (mSQLiteDatabase.insert(table, null, values) != -1) {
                    LOG_DEBUG("[setData] Insert OK!!");
                    return true;
                } else {
                    LOG_DEBUG("[setData] Insert FAIL!!");
                    return false;
                }
            } else if (nResultCnt > 1) {
                // 테이블에 레코드 키정보가 중복으로 존재하는 경우
                // 중복된 데이터를 삭제하고, 새로 설정한다.
                String DBQuiry = "delete from " + table + " where KEY=\"" + key + "\";";
                LOG_DEBUG("[getData] DBQuiry : " + DBQuiry);
                Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
                if (cursor.getCount() == 0) {
                    if (mSQLiteDatabase.insert(table, null, values) != -1) {
                        LOG_DEBUG("[setData] Delete & Insert OK!!");
                        return true;
                    } else {
                        LOG_DEBUG("[setData] Delete & Insert FAIL!!");
                        return false;
                    }
                } else {
                    LOG_DEBUG("[setData] Delete FAIL!!");
                    return false;
                }
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setData(table, key, name)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean setData(String table, String key, int nvalue) {
        try {
            String value = String.valueOf(nvalue);
            LOG_DEBUG("[setData] table [" + table + "], key [" + key + "], value [" + value + "]");
            ContentValues values = new ContentValues();
            values.put("KEY", key);
            values.put("VALUE", value);

            String SQLkey = "KEY = '" + key + "'";
            int nResultCnt = mSQLiteDatabase.update(table, values, SQLkey, null);
            LOG_DEBUG("[setData] nResultCnt = " + nResultCnt);
            if (nResultCnt == 1) {
                // 레코드 업데이트 완료
                LOG_DEBUG("[setData] Update OK!!");
                return true;
            } else if (nResultCnt == 0) {
                // 테이블에 레코드 키정보가 없는 경우, 새로 생성한다.
                if (mSQLiteDatabase.insert(table, null, values) != -1) {
                    LOG_DEBUG("[setData] Insert OK!!");
                    return true;
                } else {
                    LOG_DEBUG("[setData] Insert FAIL!!");
                    return false;
                }
            } else if (nResultCnt > 1) {
                // 테이블에 레코드 키정보가 중복으로 존재하는 경우
                // 중복된 데이터를 삭제하고, 새로 설정한다.
                String DBQuiry = "delete from " + table + " where KEY=\"" + key + "\";";
                LOG_DEBUG("[getData] DBQuiry : " + DBQuiry);
                Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
                if (cursor.getCount() == 0) {
                    if (mSQLiteDatabase.insert(table, null, values) != -1) {
                        LOG_DEBUG("[setData] Delete & Insert OK!!");
                        return true;
                    } else {
                        LOG_DEBUG("[setData] Delete & Insert FAIL!!");
                        return false;
                    }
                } else {
                    LOG_DEBUG("[setData] Delete FAIL!!");
                    return false;
                }
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setData(table, key, name)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean setData(String table, String key, Configure.SetValue evalue) {
        try {
            String value = String.valueOf(evalue);
            LOG_DEBUG("[setData] table [" + table + "], key [" + key + "], value [" + value + "]");
            ContentValues values = new ContentValues();
            values.put("KEY", key);
            values.put("VALUE", value);

            String SQLkey = "KEY = '" + key + "'";
            int nResultCnt = mSQLiteDatabase.update(table, values, SQLkey, null);
            LOG_DEBUG("[setData] nResultCnt = " + nResultCnt);
            if (nResultCnt == 1) {
                // 레코드 업데이트 완료
                LOG_DEBUG("[setData] Update OK!!");
                return true;
            } else if (nResultCnt == 0) {
                // 테이블에 레코드 키정보가 없는 경우, 새로 생성한다.
                if (mSQLiteDatabase.insert(table, null, values) != -1) {
                    LOG_DEBUG("[setData] Insert OK!!");
                    return true;
                } else {
                    LOG_DEBUG("[setData] Insert FAIL!!");
                    return false;
                }
            } else if (nResultCnt > 1) {
                // 테이블에 레코드 키정보가 중복으로 존재하는 경우
                // 중복된 데이터를 삭제하고, 새로 설정한다.
                String DBQuiry = "delete from " + table + " where KEY=\"" + key + "\";";
                LOG_DEBUG("[getData] DBQuiry : " + DBQuiry);
                Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
                if (cursor.getCount() == 0) {
                    if (mSQLiteDatabase.insert(table, null, values) != -1) {
                        LOG_DEBUG("[setData] Delete & Insert OK!!");
                        return true;
                    } else {
                        LOG_DEBUG("[setData] Delete & Insert FAIL!!");
                        return false;
                    }
                } else {
                    LOG_DEBUG("[setData] Delete FAIL!!");
                    return false;
                }
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setData(table, key, name)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean setData(String table, String key, String[] avaluename, String[] avalue) {
        try {
            LOG_DEBUG("[setData] table [" + table + "], avaluename.length [" + avaluename.length + "], avalue.length [" + avalue.length + "]");
            if (avaluename.length != avalue.length) {
                LOG_DEBUG("[setData] The lengths of values are diffrent!!");
                return false;
            }

            for (int i = 0; i < avaluename.length; i++) {
                LOG_DEBUG("[setData] avaluename [" + i + "] = " + avaluename[i]);
            }

            for (int i = 0; i < avalue.length; i++) {
                LOG_DEBUG("[setData] avalue [" + i + "] = " + avalue[i]);
            }

            ContentValues values = new ContentValues();
            values.put("KEY", key);
            for (int i = 1; i < avaluename.length; i++) {
                values.put(avaluename[i], avalue[i]);
            }

            String SQLkey = "KEY = '" + key + "'";
            int nResultCnt = mSQLiteDatabase.update(table, values, SQLkey, null);
            LOG_DEBUG("[setData] nResultCnt = " + nResultCnt);
            if (nResultCnt == 1) {
                // 레코드 업데이트 완료
                LOG_DEBUG("[setData] Update OK!!");
                return true;
            } else if (nResultCnt == 0) {
                // 테이블에 레코드 키정보가 없는 경우, 새로 생성한다.
                if (mSQLiteDatabase.insert(table, null, values) != -1) {
                    LOG_DEBUG("[setData] Insert OK!!");
                    return true;
                } else {
                    LOG_DEBUG("[setData] Insert FAIL!!");
                    return false;
                }
            } else if (nResultCnt > 1) {
                // 테이블에 레코드 키정보가 중복으로 존재하는 경우
                // 중복된 데이터를 삭제하고, 새로 설정한다.
                String DBQuiry = "delete from " + table + " where KEY=\"" + key + "\";";
                LOG_DEBUG("[getData] DBQuiry : " + DBQuiry);
                Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
                if (cursor.getCount() == 0) {
                    if (mSQLiteDatabase.insert(table, null, values) != -1) {
                        LOG_DEBUG("[setData] Delete & Insert OK!!");
                        return true;
                    } else {
                        LOG_DEBUG("[setData] Delete & Insert FAIL!!");
                        return false;
                    }
                } else {
                    LOG_DEBUG("[setData] Delete FAIL!!");
                    return false;
                }
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setData(String table, String key, String[] avaluename, String[] avalue)");
            e.printStackTrace();
            return false;
        }
    }

    public String getData(String table, String key) {
        try {
            LOG_DEBUG("[getData] table [" + table + "], key [" + key + "]");
            String strResult = null;
            String DBQuiry = "select value from " + table + " where KEY=\"" + key + "\";";
            LOG_DEBUG("[getData] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);

            while (cursor.moveToNext()) {
                strResult = cursor.getString(0);
            }
            cursor.close();
            LOG_DEBUG("[getData] strResult [" + strResult + "]");
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getData(String table, String key)");
            e.printStackTrace();
            return null;
        }
    }

    public String getData(String table, String key, String defaultValue) {
        try {
            LOG_DEBUG("[getData] table [" + table + "], key [" + key + "], defaultValue [" + defaultValue + "]");
            String strResult = null;
            String DBQuiry = "select value from " + table + " where KEY=\"" + key + "\";";
            LOG_DEBUG("[getData] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);

            while (cursor.moveToNext()) {
                strResult = cursor.getString(0);
            }
            cursor.close();
            LOG_DEBUG("[getData] strResult : " + strResult);
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getData(String table, String key, String defaultValue)");
            e.printStackTrace();
            return defaultValue;
        }
    }

    public String[] getDataAll(String table, String key) {
        try {
            LOG_DEBUG("[getDataAll] table [" + table + "], key [" + key + "]");
            String DBQuiry = "select * from " + table + " where KEY=\"" + key + "\";";
            LOG_DEBUG("[getDataAll] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
            int nRecCnt = cursor.getCount();
            LOG_DEBUG("[getDataAll] nRecCnt : " + nRecCnt);

            String[] strResult;
            int nCnt = cursor.getColumnCount();
            LOG_DEBUG("[getDataAll] nCnt : " + nCnt);

            if (nRecCnt == 0) strResult = new String[]{"NONE"};   // 정보 없음
            else if (nRecCnt == 1) strResult = new String[nCnt];   // 정보가 있고, 유일한 정보임
            else strResult = new String[]{"DUPLICATED"};   // 정보가 있으나, 중복된 정보임

            if (nRecCnt == 1) {
                if (cursor.moveToNext()) {
                    for (int i = 0; i < nCnt; i++) {
                        LOG_DEBUG("[getDataAll] " + i + " : " + cursor.getString(i));
                        strResult[i] = cursor.getString(i);
                    }
                }
            }
            cursor.close();
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getDataAll(table, key)");
            e.printStackTrace();
            return null;
        }
    }

    public String getKeyByValue(String table, String valuename, String value) {
        try {
            LOG_DEBUG("[getKeyByValue] table [" + table + "], valuename [" + valuename + "], value [" + value + "]");
            String strResult = null;
            String DBQuiry = "select KEY from " + table + " where " + valuename + "=\"" + value + "\";";
            LOG_DEBUG("[getKeyByValue] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
            while (cursor.moveToNext()) {
                strResult = cursor.getString(0);
            }
            cursor.close();
            return strResult;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getKeyByValue(table, valuename, value)");
            e.printStackTrace();
            return null;
        }
    }

    public String[] getDBByValues(String table, String[] valuenames, String[] values) {
        try {
            LOG_DEBUG("[getDBByValues] table [" + table + "], valuenames.length [" + valuenames.length + "], values.length [" + values.length + "]");
            if (valuenames.length != values.length) {
                LOG_DEBUG("[getDBByValues] The lengths of values are diffrent!!");
                return null;
            }

            String DBQuiry = "select value from " + table + " where ";
            String WhereCondition = null;
            for (int i = 0; i < valuenames.length; i++) {
                if (i == 0) WhereCondition = valuenames[i] + "=\"" + values[i];
                else if (i == valuenames.length - 1)
                    WhereCondition += " and " + valuenames[i] + "=\"" + values[i] + "\";";
                else WhereCondition += " and " + valuenames[i] + "=\"" + values[i];
            }
            DBQuiry += DBQuiry + WhereCondition;
            LOG_DEBUG("[getDBByValues] DBQuiry : " + DBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(DBQuiry, null);
            String[] strResult = new String[cursor.getColumnCount()];
            for (int i = 0; i < cursor.getColumnCount(); i++) {
                strResult[i] = cursor.getString(i);
            }

            cursor.close();
            for (int i = 0; i < strResult.length; i++) {
                LOG_DEBUG("[getDBByValues] strResult[" + i + " = " + strResult[i]);
            }
            return strResult;

        } catch (Exception e) {
            Log.e(TAG, "[Exception] getDBByValues(table, valuenames, values)");
            e.printStackTrace();
            return null;
        }
    }

    public int deleteDBKey(String strTable, String strKey) {
        try {
            return mSQLiteDatabase.delete(strTable, "KEY=\"" + strKey + "\"", null);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] deleteDBKey(strTable, strKey)");
            e.printStackTrace();
            return 99999;
        }
    }

    public int deleteDBRec(String strTable, String[] strNames, String[] strValues) {
        try {
            String strWhere = "";
            for (int i = 0; i < strNames.length; i++) {
                if (i == 0) strWhere = strNames[i] + "=\"" + strValues[i] + "\"";
                else if (i == strNames.length) strWhere += ";";
                else strWhere += " and " + strNames[i] + "=\"" + strValues[i] + "\"";
            }
            LOG_DEBUG("[deleteDBRec] strWhere = " + strWhere);
            return mSQLiteDatabase.delete(strTable, strWhere, null);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] deleteDBKey(strTable, strNames, strValues)");
            e.printStackTrace();
            return 99999;
        }
    }

    public Cursor accessDBDirectly(String strDBQuiry) {
        try {
            LOG_DEBUG("[accessDBDirectly] strDBQuiry : " + strDBQuiry);
            Cursor cursor = mSQLiteDatabase.rawQuery(strDBQuiry, null);
            return cursor;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] accessDBDirectly(strDBQuiry)");
            e.printStackTrace();
            return null;
        }
    }


}