using Microscopic_Traffic_Simulator.ViewModels.Messages;
using Microscopic_Traffic_Simulator___Model.CellularTopologyObjects;
using Microscopic_Traffic_Simulator___Model.GeometricObjects;
using Microscopic_Traffic_Simulator___Model.GeometricObjects.Lanes;
using Microscopic_Traffic_Simulator___Model.TrafficObjects;
using System.Windows;

namespace Microscopic_Traffic_Simulator.ViewModels
{
    /// <summary>
    /// Viewmodel for canvas panel.
    /// </summary>
    class CanvasViewModel : ViewModelBase
    {
        /// <summary>
        /// Current geometric topology.
        /// </summary>
        private GeometricTopology geometricTopology;
        /// <summary>
        /// Current geometric topology.
        /// </summary>        
        internal GeometricTopology GeometricTopology { get { return geometricTopology; } }

        /// <summary>
        /// Current cellular topology.
        /// </summary>        
        private CellularTopology cellularTopology;
        /// <summary>
        /// Current cellular topology.
        /// </summary>                
        internal CellularTopology CellularTopology { get { return cellularTopology; } }

        private BuildingMode buildingMode;
        internal BuildingMode BuildingMode { get { return buildingMode; } }

        /// <summary>
        /// Current lane type chosen by user.
        /// </summary>
        private LaneType currentLaneType;
        /// <summary>
        /// Current lane type chosen by user.
        /// </summary>
        internal LaneType CurrentLaneType { get { return currentLaneType; } }

        /// <summary>
        /// Initializing viewmodel.
        /// </summary>
        /// <param name="messenger">Messenger to communicate with other viewmodels.</param>
        internal CanvasViewModel(Messenger messenger)
        {
            this.messenger = messenger;
            this.messenger.GetEvent<ConstructionViewModel.GeometricTopologyMessage>().Subscribe(
                geometricTopology => this.geometricTopology = geometricTopology);
            this.messenger.GetEvent<SimulationControlViewModel.CellularTopologyMessage>().Subscribe(
                cellularTopology => this.cellularTopology = cellularTopology);
            this.messenger.GetEvent<ConstructionViewModel.BuildCellularTopologyMessage>().Subscribe(
                (geometricTopology, parameters) => buildingMode = BuildingMode.None);
            this.messenger.GetEvent<ConstructionViewModel.LaneTypeChangedMessage>().Subscribe(i => currentLaneType = i);
            this.messenger.GetEvent<ConstructionViewModel.IsConstructionModeChangedMessage>().Subscribe(
                i => buildingMode = i);
        }

        /// <summary>
        /// Builds new straight lane in geometric topology.
        /// </summary>
        /// <param name="startPoint">Start point of the lane.</param>
        /// <param name="endPoint">End point of the lane.</param>
        internal void BuildNewStraightLane(Point startPoint, Point endPoint)
        {
            geometricTopology.AddLane(new StraightLane(startPoint, endPoint));
            messenger.GetEvent<ConstructionViewModel.GeometricTopologyModifiedMessage>().Publish();
        }

        /// <summary>
        /// Builds new bezier lane in geometric topology.
        /// </summary>
        /// <param name="startPoint">Start point of the lane.</param>
        /// <param name="firstControlPoint">The first control point of the lane.</param>
        /// <param name="secondControlPoint">The second control point of the lane.</param>
        /// <param name="endPoint">End point of the lane.</param>
        internal void BuildNewBezierLaneLane(Point startPoint, Point firstControlPoint, Point secondControlPoint,
            Point endPoint)
        {
            geometricTopology.AddLane(new BezierLane(startPoint, firstControlPoint, secondControlPoint, endPoint));
            messenger.GetEvent<ConstructionViewModel.GeometricTopologyModifiedMessage>().Publish();
        }

        internal static void CreateGeneratorForLane(Lane laneWhereGeneratorToAdd)
        {
            laneWhereGeneratorToAdd.StartNode.Generator = new Generator();
        }
    }
}
