using Microscopic_Traffic_Simulator___Model.GeometricObjects.Nodes;
using Microscopic_Traffic_Simulator___Model.TrafficObjects;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace Microscopic_Traffic_Simulator___Model.GeometricObjects.Lanes
{
    /// <summary>
    /// Represent single lane.
    /// </summary>
    [Serializable]
    public abstract class Lane
    {
        /// <summary>
        /// Node on the input end of lane.
        /// </summary>
        protected StartNode startNode;
        /// <summary>
        /// Node on the input end of lane.
        /// </summary>        
        public StartNode StartNode { get { return startNode; } }

        /// <summary>
        /// Node on the output end of lane.
        /// </summary>
        protected Node endNode;
        /// <summary>
        /// Node on the output end of lane.
        /// </summary>        
        public Node EndNode { get { return endNode; } }

        /// <summary>
        /// Inner nodes on the lane.
        /// </summary>
        private List<InnerNode> innerNodes = new List<InnerNode>();
        /// <summary>
        /// Inner nodes on the lane.
        /// </summary>
        public ReadOnlyCollection<InnerNode> InnerNodes { get { return innerNodes.AsReadOnly(); } }

        /// <summary>
        /// Lane constructor.
        /// </summary>
        /// <param name="startPoint">Location of input end.</param>
        /// <param name="endPoint">Location of output end.</param>
        protected Lane(Point startPoint, Point endPoint)
        {
            startNode = new StartNode(startPoint);
            innerNodes.Add(new SensorNode(new Point(), 0.5, new Sensor("in.txt", "out.txt")));
            endNode = new EndNode(endPoint);
        }

        /// <summary>
        /// Get lane points.
        /// </summary>
        /// <param name="lanePointsMaxDistance">The maximum distance between lane points.</param>
        /// <returns>Location of lane points.</returns>
        internal abstract IEnumerable<Point> LanePoints(double lanePointsMaxDistance);

        /// <summary>
        /// Adds new inner node.
        /// </summary>
        /// <param name="innerNodeToAdd">Inner node to add.</param>
        public void AddInnerNode(InnerNode innerNodeToAdd)
        {
            innerNodes.Add(innerNodeToAdd);
        }
    }
}
