using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;

public sealed class SystemMapViewStateController : AbstractState
{
    [SerializeField]
    private AbstractState localState = null;
    [SerializeField]
    private Profile profile = null;
    [SerializeField]
    private SystemMapView mapView = null;
    [SerializeField]
    private NavPointUIPanel navPointPanel = null;
    [SerializeField]
    private FuelUICounter fuelUI = null;
    [SerializeField]
    private GameObject selectionMarker = null;
    [SerializeField]
    private GameObject currentMarker = null;
    [SerializeField]
    private JumpDistanceMarker distanceMarker = null;
    [SerializeField]
    private LineRenderer moveDistanceLine = null;
    [SerializeField]
    private OrbitalCameraControl orbitalCamera = null;
    [SerializeField]
    private PlanetsView planetsView = null;

    public NavigationPoint selectedPoint = null;

    protected override void OnEnterState()
    {
        SelectPoint(null);
        var player = profile.Player;
        var ship = player.StarShip;
        SetCurrentMarker(player.CurrentPoint);
        distanceMarker.Show(player.CurrentPoint.SystemPostition, ship.MaxJumpRadius, Mathf.Min(ship.MaxJumpRadius, ship.Fuel));
        fuelUI.Show(ship.Fuel, ship.MaxFuel);
    }

    public void ShowLocalState()
    {
        StateMachine.SetState(localState);
    }

    public void GoToMarker() // call from editor
    {
        if (selectedPoint == null)
            return;
        profile.Player.StartHyperJump(selectedPoint);
        ShowLocalState();
    }

    private void SetCurrentMarker(NavigationPoint point)
    {
        orbitalCamera.SetPosition(point.SystemPostition);
        currentMarker.transform.position = point.SystemPostition;
    }

    private void Start()
    {
        planetsView.SetPlanets(profile.Player.Planets.Select(planet => new PlanetsView.PlanetData(planet.SystemPosition, planet.Radius, planet.Color, planet == profile.Player.Planets.FirstOrDefault())).ToArray());
    }

    private void Update()
    {
        // select
        if (Input.GetMouseButtonUp(0) && EventSystem.current != null && !EventSystem.current.IsPointerOverGameObject())
        {
            SelectPoint(mapView.RaycastPoint(orbitalCamera.GetRay(Input.mousePosition)));
        }
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            ShowLocalState();
        }
    }

    private void SelectPoint(NavigationPoint point)
    {
        selectedPoint = point;
        PlaceMarker(selectedPoint);
        var ship = profile.Player.StarShip;
        navPointPanel.ShowPoint(selectedPoint, profile.Player.CurrentPoint, ship);
        if (selectedPoint == null || selectedPoint == profile.Player.CurrentPoint)
        {
            moveDistanceLine.gameObject.SetActive(false);
            PlaceMarker(null);
        }
        else
        {
            var distance = Vector3.Distance(selectedPoint.SystemPostition, profile.Player.CurrentPoint.SystemPostition);
            var canReach = ship.MaxJumpRadius > distance;
            moveDistanceLine.gameObject.SetActive(true);
            moveDistanceLine.SetPositions(new Vector3[] {
                selectedPoint.SystemPostition,
                profile.Player.CurrentPoint.SystemPostition
            });
            moveDistanceLine.startColor = moveDistanceLine.endColor = canReach ? Color.white : Color.red;
        }
    }

    private void PlaceMarker(NavigationPoint point = null)
    {
        if (point == null)
        {
            selectionMarker.SetActive(false);
        }
        else
        {
            selectionMarker.SetActive(true);
            selectionMarker.transform.position = point.SystemPostition;
        }
    }
}
