/*
 * Author: YOUR NAME HERE
 * 
 * Collaboration statement: TODO
 */

import kotlin.collections.emptyList
import java.io.File

class IMDBGraph(val performerFile: String = "src/main/resources/performer-names.tsv",
                val movieFile: String = "src/main/resources/movie-titles.tsv",
                val performanceFile: String = "src/main/resources/performances.tsv") {

    /***************** Constructor (plus helper method) *****************/

    // Our graph is represented by a pair of maps
    val performersToMovies = HashMap<String, MutableSet<String>>()
    val moviesToPerformers = HashMap<String, MutableSet<String>>()

    // These two maps just connect performer ID to name and movie ID to name; it
    // might make playing around with the data more pleasant to have access to them
    val movieIdsToTitles = HashMap<String, String>()
    val performerIdsToNames = HashMap<String, String>()

    // In the constructor, read in all of the data from the .tsv files
    init {
        // Read in performer IDs and names
        var reader = File(performerFile).bufferedReader()
        while (reader.ready()) {
            val (nameid, name) = reader.readLine().split("\t")
            performerIdsToNames[nameid] = name
        }
        reader.close()

        // Read in titles
        println("Reading titles")
        reader = File(movieFile).bufferedReader()
        while (reader.ready()) {
            val (titleid, title) = reader.readLine().split("\t")
            movieIdsToTitles[titleid] = title
        }
        reader.close()

        // Read in actual performances (a performer appearing in a movie)
        reader = File(performanceFile).bufferedReader()
        while (reader.ready()) {
            val line = reader.readLine().split("\t")
            val (titleid, nameid) = line
            addEntry(nameid, titleid)
        }
        reader.close()
    }

    /* 
    This helper method translates a performer ID to a name, and a movie ID to a title. It is not
    strictly necessary, but it makes it easier to work with the data. 
    @param id The ID of the performer or movie to translate
    @return The name of the performer or title of the movie corresponding to the given ID. If the ID is not found, returns "Unknown Performer" or "Unknown Movie" as appropriate.
    @citation Anya used Copilot's suggestion to use "startsWith" and "Unknown Performer/Movie".
    */
    fun idToName(id: String): String {
        if (id.startsWith("nm")) {
            return performerIdsToNames[id] ?: "Unknown Performer"
        } else {
            return movieIdsToTitles[id] ?: "Unknown Movie"
        }
    }

    /* This function adds a performer ID and a movie title ID to both maps. */
    fun addEntry(performerId: String, movieId: String) {
        var titles = performersToMovies[performerId]
        if (titles == null) {
            titles = mutableSetOf<String>()
            performersToMovies[performerId] = titles
        }
        titles.add(movieId)

        var names = moviesToPerformers[movieId]
        if (names == null) {
            names = mutableSetOf()
            moviesToPerformers[movieId] = names
        }
        names.add(performerId)
    }
    
    /***************** Part A: Find connected performers *****************/

    /*
        TODO: describe this function
     */
    fun connectedPerformers(performerId: String, maxDistance: Int): Set<String> {
        // TODO: Part A
        return setOf<String>()
    }
    
    /***************** Part B: Find a path between performers *****************/

    /* This data class represents a performer-movie pair. */
    data class Connection(val performerId: String, val movieId: String)

    /* This function returns a list of connections from the startPerformer to
       the endPerformer.

       For example, consider a possible shortest path from Jack Nicholson to
       Elizabeth Olsen:

       nm0000197 Jack Nicholson
         tt0082934 The Postman Always Rings Twice
       nm0001448 Jessica Lange
         tt0409379 In Secret
       nm0647634 Elizabeth Olsen

       If this function were called with nm0000197 and nm0647634, the return value
       could be this list of Connections:
       [Connection(nm0000197, tt0082934), Connection(nm0001448, tt0409379)]

       (It is possible the code might find a different set of connections between
       the two performers, but the length must be the same as the above, as the
       above is a shortest path.)

       The endPerformer is not included in the connections returned.

       If there is no connection between the two, return an empty list.
     */
    fun shortestPath(startPerformer: String, endPerformer: String): List<Connection> {
        // TODO: Part B
        return listOf<Connection>()
    }
}

/*
* Reflection: TODO
*/


/*  
* AI Log: TODO
*/