/**
 * ProjectLaogai
 *
 * Copyright 2019-2020  <seil0@mosad.xyz>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 */

package org.mosad.seil0.projectlaogai.controller.cache

import android.content.Context
import kotlinx.coroutines.Job
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
import org.mosad.seil0.projectlaogai.util.Lesson
import org.mosad.seil0.projectlaogai.util.TimetableWeek

/**
 * The TimetableController contains the timetable, subjectMap
 * and lessonMap objects. It also contains the additional subjects logic.
 * All functions ro read or update cache files are located in the CacheController.
 *
 * TODO
 *  * add second week
 *  * add configurable week to addSubject() and removeSubject(), updateAdditionalLessons()
 */
object TimetableController {

    val timetable = ArrayList<TimetableWeek>()
    val lessonMap = HashMap<String, Lesson>() // the key is courseName-subject-lessonID
    val subjectMap = HashMap<String, ArrayList<String>>() // the key is courseName

    /**
     * update the main timetable and all additional subjects, async
     */
    fun update(context: Context): List<Job> {
        return listOf(
            CacheController.updateTimetable(Preferences.course.courseName, 0, context),
            CacheController.updateTimetable(Preferences.course.courseName, 1, context),
            CacheController.updateAdditionalLessons(context)
        )
    }

    /**
     * add a subject to the subjectMap and all it's lessons
     * to the lessonMap
     * @param courseName course to which the subject belongs
     * @param subject the subjects name
     */
    fun addSubject(courseName: String, subject: String, context: Context) {
        // add subject
        if (subjectMap.containsKey(courseName)) {
            subjectMap[courseName]?.add(subject)
        } else {
            subjectMap[courseName] = arrayListOf(subject)
        }

        // add concrete lessons
        TCoRAPIController.getLessons(courseName, subject, 0).forEach { lesson ->
            addLesson(courseName, subject, lesson)
        }

        CacheController.saveAdditionalSubjects(context)
    }

    /**
     * remove a subject from the subjectMap and all it's lessons
     * from the lessonMap
     * @param courseName course to which the subject belongs
     * @param subject the subjects name
     */
    fun removeSubject(courseName: String, subject: String, context: Context) {
        // remove subject
        subjectMap[courseName]?.remove(subject)

        // remove concrete lessons
        val iterator = lessonMap.iterator()
        while (iterator.hasNext()) {
            val it = iterator.next()
            if(it.key.contains("$courseName-$subject")) {
                // remove the lesson from the lessons list
                iterator.remove() // use iterator to remove, otherwise ConcurrentModificationException

                // remove the lesson from the timetable
                val id = it.value.lessonID.split(".")
                if(id.size == 3)
                    timetable[0].days[id[0].toInt()].timeslots[id[1].toInt()].remove(it.value)
            }
        }

        CacheController.saveAdditionalSubjects(context)
    }

    /**
     * add a lesson to the lessonMap, also add it to the timetable
     */
    fun addLesson(courseName: String, subject: String, lesson: Lesson) {
        //the courseName, subject and lessonID, separator: -
        val key = "$courseName-$subject-${lesson.lessonID}"
        lessonMap[key] = lesson

        addLessonToTimetable(lesson)
    }

    /**
     * add a lesson to the timetable
     */
    fun addLessonToTimetable(lesson: Lesson) {
        val id = lesson.lessonID.split(".")
        if(id.size == 3)
            timetable[0].days[id[0].toInt()].timeslots[id[1].toInt()].add(lesson)
    }

}