package com.tsi.navi.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

import com.naver.maps.geometry.LatLng;
import com.tsi.navi.vo.NodeDirCodeVo;
import com.tsi.navi.vo.NodeVo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

public class DbQuery {

    private DbHelper dbHelper;
    private SQLiteDatabase db;

    public DbQuery(Context context) {
        dbHelper = new DbHelper(context);
    }

    public DbQuery createDatabase() throws SQLException {
        try {
            this.dbHelper.createDatabase();
        }
        catch (IOException ignored) {
        }
        return this;
    }

    public DbQuery open() throws SQLException {
        try {
            this.dbHelper.openDatabase();
            this.dbHelper.close();
            this.db = this.dbHelper.getReadableDatabase();
        }
        catch (SQLException ignored) {
        }
        return this;
    }

    public void close() {
        this.dbHelper.close();
    }

    public List<Long> getBoundsNodes(double swLat, double swLng, double neLat, double neLng) {
        String sql = "SELECT node_id, node_name, latitude, longitude, node_type, use_type " +
                     "  FROM tb_tsc_node " +
                     " WHERE latitude > " + String.valueOf(swLat) + " AND latitude < " + String.valueOf(neLat) +
                     "   AND longitude > " + String.valueOf(swLng) + " AND longitude < " + String.valueOf(neLng) + ";";

        Cursor cursor = this.db.rawQuery(sql, null);
        try {
            List<Long> nodes = new ArrayList<>();
            if (cursor.moveToFirst()) {
                do {
                    //ArrayList<Categories> categories = new ArrayList<>();
                    //categories.add(new Categories(cursor.getInt(0), cursor.getInt(1), cursor.getString(2)));
                    nodes.add(cursor.getLong(0));
                } while (cursor.moveToNext());
            }
            return nodes;
        }
        catch (Exception ignored) {
        }
        finally {
            cursor.close();
        }
        return null;
    }

    public NodeVo createNodeVo(Cursor cursor) {
        return NodeVo.builder()
                .nodeId(cursor.getLong(0))
                .name(cursor.getString(1))
                .type(cursor.getInt(4))
                .isReal(cursor.getString(5).equalsIgnoreCase("R"))
                .online(false)
                .latLng(new LatLng(cursor.getDouble(2), cursor.getDouble(3)))
                .toNodeMap(new HashMap<>())
                .fromNodeMap(new HashMap<>())
                .inDirMap(new HashSet<>())
                .runDirMap(new HashSet<>())
                .build();
    }
    public List<NodeVo> getRealNodes() {
        String sql = "SELECT node_id, node_name, latitude, longitude, node_type, use_type FROM tb_tsc_node WHERE use_type = 'R'" + ";";

        Cursor cursor = this.db.rawQuery(sql, null);
        try {
            List<NodeVo> nodes = new ArrayList<>();
            if (cursor.moveToFirst()) {
                do {
                    nodes.add(createNodeVo(cursor));
                } while (cursor.moveToNext());
            }
            return nodes;
        }
        catch (Exception ignored) {
        }
        finally {
            cursor.close();
        }
        return null;
    }

    public List<NodeVo> getNodes() {
        String sql = "SELECT node_id, node_name, latitude, longitude, node_type, use_type FROM tb_tsc_node" + ";";

        Cursor cursor = this.db.rawQuery(sql, null);
        try {
            List<NodeVo> nodes = new ArrayList<>();
            if (cursor.moveToFirst()) {
                do {
                    nodes.add(createNodeVo(cursor));
                } while (cursor.moveToNext());
            }
            return nodes;
        }
        catch (Exception ignored) {
        }
        finally {
            cursor.close();
        }
        return null;
    }

    public List<NodeDirCodeVo> getNodeDir() {
        String sql = "SELECT node_id, dir_code FROM tb_tsc_node_dir" + ";";

        Cursor cursor = this.db.rawQuery(sql, null);
        try {
            List<NodeDirCodeVo> nodes = new ArrayList<>();
            if (cursor.moveToFirst()) {
                do {
                    nodes.add(NodeDirCodeVo.builder()
                            .nodeId(cursor.getLong(0))
                            .dirCode(cursor.getString(1))
                            .build());
                } while (cursor.moveToNext());
            }
            return nodes;
        }
        catch (Exception ignored) {
        }
        finally {
            cursor.close();
        }
        return null;
    }
    /*public List<NodeDirVo> getNodeDir() {
        String sql = "SELECT st_node_id, ed_node_id, length FROM tb_tsc_node_dir" + ";";

        Cursor cursor = this.db.rawQuery(sql, null);
        try {
            List<NodeDirVo> nodes = new ArrayList<>();
            if (cursor.moveToFirst()) {
                do {
                    nodes.add(NodeDirVo.builder()
                            .stNodeId(cursor.getLong(0))
                            .edNodeId(cursor.getLong(1))
                            .length(cursor.getInt(2))
                            .build());
                } while (cursor.moveToNext());
            }
            return nodes;
        }
        catch (Exception ignored) {
        }
        finally {
            cursor.close();
        }
        return null;
    }*/

    public int getNodeCount(NodeVo node) {
        String sql = "SELECT count(1) as node_cnt " +
                "  FROM tb_tsc_node " +
                " WHERE node_id = " + String.valueOf(node.getNodeId()) + ";";

        int result = 1;
        Cursor cursor = this.db.rawQuery(sql, null);
        try {
            if (cursor.moveToFirst()) {
                result = cursor.getInt(0);
            }
        }
        catch (Exception ignored) {
        }
        finally {
            cursor.close();
        }
        return result;
    }
    public long insertNodeInfo(NodeVo node) {
        long result = -1;

        ContentValues cv = new  ContentValues();
        cv.put("NODE_ID",   node.getNodeId());
        cv.put("NODE_NAME", node.getName());
        cv.put("LATITUDE",  node.getLatLng().latitude);
        cv.put("LONGITUDE", node.getLatLng().longitude);
        cv.put("NODE_TYPE", node.getType());
        cv.put("USE_TYPE",  "R");

        try {
            result = this.db.insert("tb_tsc_node", null, cv);
        }
        catch (Exception ignored) {
        }
        finally {
        }
        return result;
    }

}
