package com.tsi.navi.activity;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.location.Location;
import android.util.Log;
import android.view.Gravity;

import com.naver.maps.geometry.LatLng;
import com.naver.maps.geometry.LatLngBounds;
import com.naver.maps.map.CameraPosition;
import com.naver.maps.map.CameraUpdate;
import com.naver.maps.map.LocationTrackingMode;
import com.naver.maps.map.NaverMap;
import com.naver.maps.map.overlay.CircleOverlay;
import com.naver.maps.map.overlay.LocationOverlay;
import com.naver.maps.map.overlay.Marker;
import com.naver.maps.map.overlay.OverlayImage;
import com.tsi.navi.TsiNaviApplication;
import com.tsi.navi.database.DbQuery;
import com.tsi.navi.vo.NodeDirCodeVo;
import com.tsi.navi.vo.NodeVo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class MainActivityUtils {

    private static List<Location> locationList = new LinkedList<Location>();

    public static List<Location> getLocationList() {
        return locationList;
    }
    public static void addLocation(Location location) {
        if (locationList.size() > 10) {
            locationList.remove(0);
        }
        locationList.add(location);
    }
    public static int getLocationSize() {
        return locationList.size();
    }

    public static void initDatabase(Context context) {
        DbQuery dbQuery = new DbQuery(context);
        dbQuery.createDatabase();
        dbQuery.open();
        List<NodeVo> nodes = dbQuery.getNodes();
        if (nodes != null) {
            for (NodeVo node : nodes) {
                TsiNaviApplication.getNodeMap().put(node.getNodeId(), node);
            }
        }

        float[] calDistance = {-999, -999};
        List<NodeDirCodeVo> nodeDirs = dbQuery.getNodeDir();
        if (nodeDirs != null) {
            for (NodeDirCodeVo nodeDir : nodeDirs) {
                NodeVo node = TsiNaviApplication.getNodeMap().get(nodeDir.getNodeId());
                if (node == null) {
                    Log.e("NodeDir", "Not Found: " + nodeDir.getNodeId());
                    continue;
                }

                //Log.e("INFO", nodeDir.getNodeId() + " --> " + nodeDir.getDirCode());
                //List<String> links = TsiUtils.split(nodeDir.getDirCode(), ",");
                String[] links = nodeDir.getDirCode().trim().split("\\|");
                //String result = Arrays.deepToString(splits);
                //List<String> links = TsiUtils.split(nodeDir.getDirCode().trim(), "\\|");
                //Log.e("INFO", nodeDir.getNodeId() + ": " + nodeDir.getDirCode().trim() + " --> " + links.toString() + ", " + result);
                for (String codes : links) {
                    //node.getInDirMap().add(Integer.parseInt(codes));
                    String[] dirs = codes.split(",");
                    if (dirs.length == 2) {
                        long fromNodeId = Long.parseLong(dirs[0]);
                        int dirCode = Integer.parseInt(dirs[1]);
                        NodeVo fromNode = TsiNaviApplication.getNodeMap().get(fromNodeId);
                        if (fromNode != null) {
                            fromNode.getToNodeMap().put(dirCode, node);     // 진출방향코드, 진출노드
                            node.getFromNodeMap().put(dirCode, fromNode);   // 진입방향코드, 진입노드
                        }
                        node.getInDirMap().add(dirCode);  // 진입시 방향 코드
                        node.getRunDirMap().add(TsiNaviApplication.getDirection().getSignal2RunDirection(dirCode));
                    }
                }
            }
        }
        for (Map.Entry<Long, NodeVo> obj : TsiNaviApplication.getNodeMap().entrySet()) {
            NodeVo node = obj.getValue();
            //Log.e("INFO", node.getNodeId() + ": " + node.getInDirMap().toString() + " --> " + node.getToNodeMap().toString());
/*
            Iterator<Integer> iter = obj.getValue().getInDirMap().iterator();
            while(iter.hasNext()){
                System.out.print(iter.next() + " ");
            }
*/
/*
            Log.e("NodeInfo", "insert into tb_tsc_node_dir(node_id, dir_code) values (" + node.getNodeId() + ", '");
            for (Map.Entry<Integer, Long> dir : node.getInDirMap().entrySet()) {
                NodeVo stNode = TsiNaviApplication.getNodeMap().get(dir.getValue());
                //Log.e("NodeInfo", node.getNodeId()+ ": " + stNode.getName() + " --> " + node.getName() + ": " + dir.getKey());
                Log.e("NodeInfo", dir.getKey() + ",");
            }
            Log.e("NodeInfo", "');");
*/

            /*for (NodeDirVo dirVo : node.getDirMap()) {
                NodeVo edNode = TsiNaviApplication.getNodeMap().get(dirVo.getEdNodeId());
                Log.e("NodeInfo", node.getName() + " --> " + edNode.getName() + ": " + dirVo.getDirCode());
            }*/
        }
        dbQuery.close();
    }
    public static void initMap(NaverMap naverMap) {

        naverMap.setLocationTrackingMode(LocationTrackingMode.Face);

        naverMap.setLayerGroupEnabled(NaverMap.LAYER_GROUP_BUILDING, true);    // 건물 표시
        // 줌 범위 제한
        naverMap.setMinZoom(10.0);  //최소
        naverMap.setMaxZoom(21.0);  //최대

        // 카메라 영역 제한
        LatLng northWest = new LatLng(31.43, 122.37);   //서북단
        LatLng southEast = new LatLng(44.35, 132.0);    //동남단
        naverMap.setExtent(new LatLngBounds(northWest, southEast));
        /*naverMap.setExtent(MapConstants.EXTENT_KOREA.getSouthWest(),
                MapConstants.EXTENT_KOREA.getNorthWest(),
                MapConstants.EXTENT_KOREA.getNorthEast(),
                MapConstants.EXTENT_KOREA.getSouthEast(),
                MapConstants.EXTENT_KOREA.getSouthWest()));*/

        // UI 설정
        naverMap.getUiSettings().setCompassEnabled(true);              // 나침반, 기본값: true
        naverMap.getUiSettings().setScaleBarEnabled(true);             // 축척바, 기본값: true
        naverMap.getUiSettings().setZoomControlEnabled(false);         // 줌버튼, 기본값: true
        naverMap.getUiSettings().setLocationButtonEnabled(false);      // 현재위치, 기본값: false
        naverMap.getUiSettings().setLogoGravity(Gravity.LEFT | Gravity.BOTTOM);

/*
        CompassView compassView = findViewById(R.id.compass);
        compassView.setMap(mNaverMap);
        ScaleBarView scaleBarView = findViewById(R.id.scalebar);
        scaleBarView.setMap(mNaverMap);
        ZoomControlView zoomControlView = findViewById(R.id.zoom);
        zoomControlView.setMap(mNaverMap);
        LocationButtonView locationButtonView = findViewById(R.id.location);
        locationButtonView.setMap(mNaverMap);*/
    }

    public static void setupMap(NaverMap naverMap, double trackingZoom) {
        // 기본적으로 네이버지도에서 제공되는 지도는 Basic, Navi, Satellite, Hybrid, Terrain 등 5가지 입니다.
        // 기본 디폴트는 Basic 입니다.

        // 배경 지도 선택
        naverMap.setMapType(NaverMap.MapType.valueOf(TsiNaviApplication.getMapConfig().getType()));
        naverMap.setNightModeEnabled(TsiNaviApplication.getMapConfig().isNightMode());
        naverMap.setBuildingHeight(0.5f);
        //naverMap.setBuildingHeight(1.0F);

        // Night Mode
        boolean nightModeEnabled = naverMap.isNightModeEnabled();
        if (nightModeEnabled != TsiNaviApplication.getMapConfig().isNightMode()) {
            naverMap.setBackgroundColor(nightModeEnabled ? NaverMap.DEFAULT_BACKGROUND_COLOR_DARK : NaverMap.DEFAULT_BACKGROUND_COLOR_LIGHT);
            naverMap.setBackgroundResource(nightModeEnabled ? NaverMap.DEFAULT_BACKGROUND_DRWABLE_DARK : NaverMap.DEFAULT_BACKGROUND_DRWABLE_LIGHT);
        }

        // Run Drive zoom
        int newZoom = TsiNaviApplication.getMapConfig().getTrackingZoom();
        int curZoom = (int)naverMap.getCameraPosition().zoom;
        if ((int)trackingZoom != newZoom || newZoom != curZoom) {
            trackingZoom = newZoom;
            CameraUpdate cameraUpdate = CameraUpdate.scrollAndZoomTo(naverMap.getCameraPosition().target, trackingZoom);
            naverMap.moveCamera(cameraUpdate);
        }
    }

    public static void initMapOverlay(NaverMap naverMap, int iconId, boolean isTabs6) {
        LocationOverlay locationOverlay = naverMap.getLocationOverlay();
        locationOverlay.setVisible(true);
        locationOverlay.setIcon(OverlayImage.fromResource(iconId));
        locationOverlay.setIconWidth(LocationOverlay.SIZE_AUTO);
        locationOverlay.setIconHeight(LocationOverlay.SIZE_AUTO);
/*
        locationOverlay.setIconWidth(isTabs6 ? 300 : 200);
        locationOverlay.setIconHeight(isTabs6 ? 300 : 200);
*/
    }

    public static Marker createNodeMarker(NaverMap map, NodeVo node, int realIconId, int dummyIconId) {
        //Marker marker = new Marker(new LatLng(node.getLat(), node.getLng()));
        Marker marker = new Marker(node.getLatLng());
        if (node.isReal()) {
            marker.setTag(node.getName());
            marker.setCaptionTextSize(14);
            marker.setCaptionColor(Color.BLACK);
            marker.setCaptionHaloColor(Color.YELLOW);
            marker.setCaptionText(node.getName());

            marker.setIcon(OverlayImage.fromResource(realIconId));
            marker.setMap(map);
        }
        else {
            marker.setTag("x");
            /*marker.setTag(node.getName());
            marker.setCaptionTextSize(14);
            marker.setCaptionColor(Color.BLACK);
            marker.setCaptionHaloColor(Color.YELLOW);
            marker.setCaptionText(node.getName());*/
            marker.setIcon(OverlayImage.fromResource(dummyIconId));
            marker.setMap(null);
        }
        marker.setCaptionMinZoom(14);

        //marker.setForceShowCaption(true);
        marker.setMinZoom(11);
        marker.setIconPerspectiveEnabled(true);
        //marker.setSubCaptionTextSize(10);
        //marker.setSubCaptionColor(Color.RED);
        //marker.setSubCaptionText(String.valueOf(node.getNodeId()));
        //marker.setSubCaptionMinZoom(13);

        return marker;
    }
    public static List<Long> getBoundsNodes(DbQuery dbQuery, LatLngBounds bounds) {
        return dbQuery.getBoundsNodes(
                bounds.getSouthWest().latitude,
                bounds.getSouthWest().longitude,
                bounds.getNorthEast().latitude,
                bounds.getNorthEast().longitude);
    }

    // 현재 카메라가 보고있는 위치
    public static LatLng getCurrentPosition(NaverMap map) {
        CameraPosition cameraPosition = map.getCameraPosition();
        return new LatLng(cameraPosition.target.latitude, cameraPosition.target.longitude);
    }

    public static List<LatLng> getDirectionBounds(boolean trackingMode, NaverMap map, CircleOverlay circleOverlay, LatLng location) {
        List<LatLng> coords = new ArrayList<>();

        int distanceWidth = 60;

        PointF p1 = new PointF(10, 10);
        PointF p2 = new PointF(10, 11);
        // for 루프 돌면서 거리 값이 근사치로 나올때 확인하는 방법도 있음.
        double getMetersPerPixel = map.getProjection().getMetersPerPixel();
        Log.e("getMetersPerPixel", "getMetersPerPixel: " + getMetersPerPixel);
        Log.e("getMetersPerPixel", "getMetersPerPixel: " + getMetersPerPixel * 60);

        LatLng latLng1 = map.getProjection().fromScreenLocationAt(p1, map.getCameraPosition().zoom, map.getCameraPosition().tilt, map.getCameraPosition().bearing, false);
        LatLng latLng2 = map.getProjection().fromScreenLocationAt(p2, map.getCameraPosition().zoom, map.getCameraPosition().tilt, map.getCameraPosition().bearing, false);
        double unitMeter = latLng1.distanceTo(latLng2);
        float uPixel = (float)(unitMeter * 60);
        LatLngBounds areaBounds = circleOverlay.getBounds();
        PointF ptL = map.getProjection().toScreenLocationAt(areaBounds.getSouthWest(), map.getCameraPosition().zoom, map.getCameraPosition().tilt, map.getCameraPosition().bearing, false);
        PointF ptR = map.getProjection().toScreenLocationAt(areaBounds.getSouthEast(), map.getCameraPosition().zoom, map.getCameraPosition().tilt, map.getCameraPosition().bearing, false);
        float uX = Math.abs(ptR.x - ptL.x);
        uX /= 2;
        uX = 285;
        LatLng center = new LatLng(map.getCameraPosition().target.latitude, map.getCameraPosition().target.longitude);;
        PointF ptCenter = map.getProjection().toScreenLocation(center);
        PointF ptBL = new PointF(ptCenter.x-uX, ptCenter.y);
        PointF ptBR = new PointF(ptCenter.x+uX, ptCenter.y);
        PointF ptTL = new PointF(ptCenter.x-uX, 20);
        PointF ptTR = new PointF(ptCenter.x+uX, 20);


        LatLng bottomLeft = map.getProjection().fromScreenLocation(ptBL);
        LatLng bottomRight = map.getProjection().fromScreenLocation(ptBR);
        LatLng topLeft = map.getProjection().fromScreenLocation(ptTL);
        LatLng topRight = map.getProjection().fromScreenLocation(ptTR);
/*
        LatLng bottomLeft = center.offset(0, -60);
        LatLng bottomRight = center.offset(0, 60);
        LatLng topLeft = center.offset(300, -60);
        LatLng topRight = center.offset(300, 60);
*/

        circleOverlay.setCenter(center);
        Log.e("center",   "  center: " + center.toString());
        Log.e("leftPos",  " leftPos: " + bottomLeft.toString());
        Log.e("rightPos", "rightPos: " + bottomRight.toString());
        LatLng coord = map.getProjection().fromScreenLocation(ptCenter);
        Log.e("center1",   "  center: " + ptCenter.toString());
        Log.e("center2",   "  center: " + coord.toString());

        LatLngBounds mapBounds = map.getCoveringBounds();
        double bottomLatitude = areaBounds.getSouthWest().latitude + ((areaBounds.getNorthEast().latitude - areaBounds.getSouthWest().latitude) / 2);
        bottomLatitude = bottomLeft.latitude;
        LatLng topLatLng = map.getProjection().fromScreenLocation(new PointF(0, 0));
        //LatLng topLatLng = map.getProjection().fromScreenLocationAt(new PointF(0, 0), map.getCameraPosition().zoom, 0, -map.getCameraPosition().bearing, false);
        double topLatitude = topLatLng.latitude;
/*
        Collections.addAll(coords,
                areaBounds.getSouthWest(),
                areaBounds.getSouthEast(),
                areaBounds.getNorthEast(),
                areaBounds.getNorthWest(),
                areaBounds.getSouthWest()
        );
*/

        Collections.addAll(coords,
                bottomLeft,
                bottomRight,
                topRight,
                topLeft,
                bottomLeft
                );
        return coords;
    }
}
