﻿using UnityEngine;
using System.Collections;
using packt.FoodyGO.Mapping;
using System.Collections.Generic;
using packt.FoodyGO.Database;
using packt.FoodyGo.Utils;

namespace packt.FoodyGO.Services
{
    public class MonsterService : MonoBehaviour
    {
        public GPSLocationService gpsLocationService;
        private double lastTimestamp;

        [Header("Monster Spawn Parameters")]
        public float monsterSpawnRate = .75f;
        public float latitudeSpawnOffset = .001f;
        public float longitudeSpawnOffset = .001f;

        [Header("Monster Visibility")]
        public float monsterHearDistance = 200f;
        public float monsterSeeDistance = 100f;
        public float monsterLifetimeSeconds = 30;
        public List<Monster> monsters;
        
        // Use this for initialization
        void Start()
        {
            monsters = new List<Monster>();

            StartCoroutine(CleanupMonsters());
        }

        private IEnumerator CleanupMonsters()
        {
            while (true)
            {
                var now = Epoch.Now;
                var list = monsters.ToArray();
                for(int i = 0; i < list.Length; i++)
                {
                    if(list[i].spawnTimestamp + monsterLifetimeSeconds > now)
                    {
                        print("Cleaning up monster");
                        monsters.Remove(list[i]);
                    }
                }
                yield return new WaitForSeconds(5);
            }
        }

        // Update is called once per frame
        void Update()
        {
            if (gpsLocationService != null &&
                gpsLocationService.IsServiceStarted &&
                gpsLocationService.PlayerTimestamp > lastTimestamp)
            {
                lastTimestamp = gpsLocationService.PlayerTimestamp;

                //update the monsters around the player
                CheckMonsters();
            }
        }

        private void CheckMonsters()
        {            
            if (Random.value > monsterSpawnRate)
            {
                var mlat = gpsLocationService.Latitude + Random.Range(-latitudeSpawnOffset, latitudeSpawnOffset);
                var mlon = gpsLocationService.Longitude + Random.Range(-longitudeSpawnOffset, longitudeSpawnOffset);
                var monster = new Monster
                {
                    location = new MapLocation(mlon, mlat),
                    spawnTimestamp = gpsLocationService.PlayerTimestamp
                };
                monsters.Add(monster);
            }

            //store players location for easy access in distance calculations
            var playerLocation = new MapLocation(gpsLocationService.Longitude, gpsLocationService.Latitude);
            //get the current Epoch time in seconds
            var now = Epoch.Now;

            foreach (Monster m in monsters)
            {
                var d = MathG.Distance(m.location, playerLocation);
                if (MathG.Distance(m.location, playerLocation) < monsterSeeDistance)
                {
                    m.lastSeenTimestamp = now;
                    print("Monster seen, distance " + d + " started at " + m.spawnTimestamp);
                    continue;
                }

                if (MathG.Distance(m.location, playerLocation) < monsterHearDistance)
                {
                    m.lastHeardTimestamp = now;
                    print("Monster heard, distance " + d + " started at " + m.spawnTimestamp);
                    continue;
                }

                //hide monsters that can't be seen or heard

            }               
        }

        private Vector3 ConvertToWorldSpace(float longitude, float latitude)
        {
            //convert GPS lat/long to world x/y 
            var x = ((GoogleMapUtils.LonToX(longitude)
                - gpsLocationService.mapWorldCenter.x) * gpsLocationService.mapScale.x);
            var y = (GoogleMapUtils.LatToY(latitude)
                - gpsLocationService.mapWorldCenter.y) * gpsLocationService.mapScale.y;
            return new Vector3(-x, 0, y);
        }
    }
}
