(function() {

    

    function fetchSeed(id) {
        var HttpRequest = Packages.com.gmt2001.HttpRequest,
        HashMap = Packages.java.util.HashMap,
        JSONObject = Packages.org.json.JSONObject,
        header = new HashMap(0),
        json = new JSONObject('{}');
        var request = HttpRequest.getData(HttpRequest.RequestType.GET,'https://www.geoguessr.com/api/v3/games/'+id,json.toString(),header);
        if (request.success) {
        var data = new JSONObject(request.content)
        return data;
        }
	};
	function getCountryBDC(location) {
        var HttpRequest = Packages.com.gmt2001.HttpRequest,
        HashMap = Packages.java.util.HashMap,
        JSONObject = Packages.org.json.JSONObject,
        header = new HashMap(0),
        json = new JSONObject('{}');
        const BDC_KEY = "067c718d2bbd4a2ba8d0645e1633cac2";
        var request = HttpRequest.getData(HttpRequest.RequestType.GET,'https://api.bigdatacloud.net/data/reverse-geocode?latitude='+location.lat+'&longitude='+location.lng+'&key='+BDC_KEY,json.toString(),header);
        if (request.success) {
        var data = new JSONObject(request.content)
        return data.countryCode;
        }
	};
    function moveFrom(coords, angle, distance) {
        var radianAngle = (angle * Math.PI) / 180;
        var x = 0 + distance * Math.cos(radianAngle);
        var y = 0 + distance * Math.sin(radianAngle);
        var newLat = coords.lat + y * M;
        var newLng = coords.lng + (x * M) / Math.cos(coords.lat * (Math.PI / 180));
        return { lat: newLat, lng: newLng };
    }
	function getSurroundings (location) {
		const meters = 100;
		const R_EARTH = 6378.137;
		const M = 1 / (((2 * Math.PI) / 360) * R_EARTH) / 1000;
		var coordinates = [location];
		for (var angle = 0; angle < 360; angle += 45) {
			coordinates.push(moveFrom({ lat: location.lat, lng: location.lng }, angle, meters));
		}
		return coordinates;
	};

	function isCoordinates (coordinates) {
		const regex = /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/g;
		return regex.test(coordinates);
	};

	function calculateScale(bounds){
        return haversineDistance({ lat: bounds.min.lat, lng: bounds.min.lng }, { lat: bounds.max.lat, lng: bounds.max.lng }) / 7.458421;
    }

	function haversineDistance(mk1, mk2){
		const R = 6371.071;
		const rlat1 = mk1.lat * (Math.PI / 180);
		const rlat2 = mk2.lat * (Math.PI / 180);
		const difflat = rlat2 - rlat1;
		const difflon = (mk2.lng - mk1.lng) * (Math.PI / 180);
		const km =
			2 *
			R *
			Math.asin(Math.sqrt(Math.sin(difflat / 2) * Math.sin(difflat / 2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin(difflon / 2) * Math.sin(difflon / 2)));
		return km;
	};

	function calculateScore(distance, scale){
        return Math.round(5000 * Math.pow(0.99866017, (distance * 1000) / scale));
    }

	function normalize(val){
        return val.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
    }

	function isMatch(input, key){
        return input.length >= 3 && key.includes(input) && input.length <= key.length;
    }

	function findCountry(input){
		const normalized = GameHelper.normalize(input);
		return countryCodesNames.find((country) => country.code === normalized || GameHelper.isMatch(normalized, country.names.toLowerCase()));
	};

    var isOpen =  $.getSetIniDbBoolean('chatguessr', 'isOpen', false),
        seed = {},
        guesses = {
            '1':[
                {user:'Alpha',location:'0,0',distance:5,score:2,streak:0},
                {user:'Beta',location:'5,0',distance:100,score:3,streak:0},
                {user:'Charlie',location:'6,6',distance:1000,score:0,streak:0},
                {user:'Delta',location:'42,6',distance:1,score:5,streak:1}
            ],
            '2':[

            ],
        };

    function dbSetSeed(id) {
        $.inidb.SetBoolean("chatguessr", "isOpen", "", open);
        isOpen = open;
    }
    
    function dbSetOpen(open) {
        $.inidb.SetBoolean("chatguessr", "isOpen", "", open);
        isOpen = open;
        sendData('status',open);
    }
    function dbClearGuesses() {
        guesses = {};
        $.inidb.SetString("chatguessr", "guesses", JSON.stringify(guesses));
        sendData('guesses',guesses);
    }

    function dbAddGuess(user,position) {
        if(guesses[user] && guesses[user].length > 0){
        }else if(isCoordinates(position)){
            guesses[user] = position;
            $.inidb.SetString("chatguessr", "guesses", JSON.stringify(guesses));
            sendData('guesses',JSON.stringify(guesses));
        }
    }

    function sendData(tpe, data) {
        $.panelsocketserver.sendJSONToAll(JSON.stringify({
            'eventFamily': 'chatguessr',
            'eventType': tpe,
            'data': data
        }));
    }

    function isCoordinates(coordinates) {
		const regex = /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/g;
		return regex.test(coordinates);
	};

    $.bind('command', function(event) {

        const sender = "" + event.getSender().toLowerCase(),
            command = event.getCommand(),
            args = event.getArgs(),
            action = args[0];

        if (command.equalsIgnoreCase('g')) {
            if(isOpen) DBAddG(sender,args);
        }else if (command.equalsIgnoreCase('cg')) {
            //send url 
            //$.say($.whisperPrefix(sender) + $.lang.get('chatguessr.help', ' Use "!cg [open | close | ...]" to open/close the feature.'));
        }else if(command.equalsIgnoreCase('cga')){
            if(action.equalsIgnoreCase('open')){
                isOpen = true;
                $.getSetIniDbBoolean('cgstatus', 'isOpen', true);
            }else if(action.equalsIgnoreCase('close')){
                isOpen = false;
                $.getSetIniDbBoolean('cgstatus', 'isOpen', false)
            }else if(action.equalsIgnoreCase('start')){
                seed = GameHelper.fetchSeed(args[1]);
            }else if(action.equalsIgnoreCase('end')){
                isOpen = false;
                $.getSetIniDbBoolean('cgstatus', 'isOpen', false)
            }else if(action.equalsIgnoreCase('refresh')){
                var newseed = GameHelper.fetchSeed(args[1]);
            }else if(action.equalsIgnoreCase('gg')){
                sendData('guesses',JSON.stringify(guesses));
            }
        }
    });

    $.bind('initReady', function() {
        $.registerChatCommand('./custom/custom/chatguessr.js', 'cg',7);
        $.registerChatCommand('./custom/custom/chatguessr.js', 'g',7);
        $.registerChatCommand('./custom/custom/chatguessr.js', 'cga',7);
        $.registerChatSubcommand('cga', 'open', 1);
        $.registerChatSubcommand('cga', 'close', 1);
        $.registerChatSubcommand('cga', 'start', 1);
        $.registerChatSubcommand('cga', 'end', 1);
        $.registerChatSubcommand('cga', 'refresh', 1);
        $.registerChatSubcommand('cga', 'gg', 1);
    });

})();