package com.saeedsh.subway;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import com.saeedsh.subway.Route.Colour;
import com.saeedsh.subway.Route.Direction;

public class SubwayModel {

	private static SubwayModel subwayModel;
	private static List<List<Route>> subwayMap = new ArrayList<>();
	private static List<Schedule> schedules = new ArrayList<>();

	private SubwayModel() {
	}

	public static SubwayModel getInstance() {

		Station kingStation = new Station("King");
		List<LocalTime> kingArrivalTimes = new LinkedList<LocalTime>(
				Arrays.asList(LocalTime.of(10, 10), LocalTime.of(10, 20), LocalTime.of(10, 30), LocalTime.of(10, 50)));

		Station collegeStation = new Station("College");
		List<LocalTime> collegeArrivalTimes = new LinkedList<LocalTime>(
				Arrays.asList(LocalTime.of(9, 40), LocalTime.of(9, 50), LocalTime.of(10, 0), LocalTime.of(10, 15)));

		Schedule kingNorthboundSchedule = new Schedule(kingStation, kingArrivalTimes, Direction.NORTH);
		Schedule collegeSouthboundSchedule = new Schedule(collegeStation, collegeArrivalTimes, Direction.SOUTH);

		schedules.add(kingNorthboundSchedule);
		schedules.add(collegeSouthboundSchedule);

		if (subwayModel == null) {
			subwayModel = new SubwayModel();
		}
		return subwayModel;
	}

	// Add a line which could be a subway line or sub-line
	public static List<Route> addLine(List<String> stationNames, Direction direction, Colour colour) {

		List<Route> line = new LinkedList<>();
		for (int i = 0; i < stationNames.size() - 1; i++) {
			line.add(new Route(new Station(stationNames.get(i)), new Station(stationNames.get(i + 1)), direction,
					colour));
		}

		return line;
	}

	public List<List<Route>> getSubwayMap() {
		return subwayMap;
	}

	public void setSubwayMap(List<List<Route>> subwayMap) {
		SubwayModel.subwayMap = subwayMap;
	}

	public List<Schedule> getSchedules() {
		return schedules;
	}

	public void setSchedules(List<Schedule> schedules) {
		SubwayModel.schedules = schedules;
	}

	public LocalTime getNextTrainArrival(Station station, LocalTime time, Direction direction) {

		for (Schedule s : schedules) {
			if (s.getStation().getName().equals(station.getName())) {
				if (direction.equals(s.getDirection())) {
					int nextIndex = Collections.binarySearch(s.getArrivalTimes(), time);

					// Time not found in schedule
					if (nextIndex < 0) {
						return s.getArrivalTimes().get(-(nextIndex + 1));
					} else if (nextIndex == s.getArrivalTimes().size() - 1) { // Last train
						return s.getArrivalTimes().get(0);
					} else {
						return s.getArrivalTimes().get(nextIndex + 1);
					}
				}
			}
		}

		return LocalTime.of(3, 0);
	}

}