#define OLC_PGE_APPLICATION
#include "pixelGameEngine.h"
#include "olcutils.h"

using namespace olc;

struct Room{
    std::vector<std::string>connections;
    std::map<std::string,int>paths;
    int flowValue=0;
    std::string name="";
    friend std::ostream&operator<<(std::ostream&out,Room&rhs){
        out<<"Valve "<<rhs.name<<": Flow Rate - "<<rhs.flowValue<<" (Connects to: ";
        for (int i=0;i<rhs.connections.size();i++){
            std::string conn=rhs.connections[i];
            if (i!=0){
                out<<",";
            }
            out<<conn;
        }
        out<<")";
        return out;
    }
};

std::map<std::string,Room>rooms;
int maxFlow=0;
int iterations=0;
int branchesRemaining=0;

int findRoute(std::string start,std::string end,std::map<std::string,bool>visited,int dist){
    visited[start]=true;
    int distance=INFINITY;
    Room r=rooms[start];
    for (int i=0;i<r.connections.size();i++){
        if (r.connections[i]==end){
            return dist+1;
        }
    }
    for (int i=0;i<r.connections.size();i++){
        if (visited.find(r.connections[i])==visited.end()){
            int result=findRoute(r.connections[i],end,visited,dist+1);
            if (result<distance){
                distance=result;
            }
        }
    }
    return distance;
}

void explore(std::string currentRoom,std::map<std::string,bool>visitedvalves,int flowRate,int minute,int flowTotal,std::string journey,std::string flowTotals){

    //std::cout<<"Exploring "<<currentRoom<<" Time Passed: "<<minute<<". Flow Rate: "<<flowRate<<", Flow Total: "<<flowTotal<<" Journey: "<<journey<<" Totals:"<<flowTotals<<std::endl;
    visitedvalves[currentRoom]=true;

    int previousFlowTotal=flowTotal;
    std::string prevFlowTotal=flowTotals;
    for (int i=minute;i<30;i++){
        flowTotal+=flowRate;
        flowTotals+="->"+std::to_string(flowTotal);
    }
    if (flowTotal>maxFlow){
        maxFlow=flowTotal;
        std::cout<<"New max found: "<<maxFlow<<std::endl;
    }
    //std::cout<<" Maxed Out: "<<currentRoom<<" Time Passed: "<<minute<<". Flow Rate: "<<flowRate<<", Flow Total: "<<flowTotal<<" Journey: "<<journey<<" Totals:"<<flowTotals<<std::endl;

    flowTotals=prevFlowTotal;
    flowTotal=previousFlowTotal;

    for (std::map<std::string,Room>::iterator it=rooms.begin();it!=rooms.end();++it){
        if (visitedvalves.find(it->first)==visitedvalves.end()&&rooms[it->first].flowValue>0){
            //We haven't tried going here yet.
            if (minute+rooms[currentRoom].paths[it->first]<30){
                for (int i=0;i<rooms[currentRoom].paths[it->first];i++){
                    flowTotal+=flowRate;
                    flowTotals+="->"+std::to_string(flowTotal);
                }
                explore(it->first,visitedvalves,flowRate,minute+rooms[currentRoom].paths[it->first],flowTotal,journey+"->"+it->first,flowTotals);
                flowTotal+=flowRate;
                flowTotals+="->"+std::to_string(flowTotal);
                explore(it->first,visitedvalves,flowRate+rooms[it->first].flowValue,minute+rooms[currentRoom].paths[it->first]+1,flowTotal,journey+"->"+it->first,flowTotals);
                flowTotal=previousFlowTotal;
                flowTotals=prevFlowTotal;
            }
        }
    }
}

int main()
{
	std::ifstream file("input");
    while (file.good()){
        std::string line;
        std::getline(file,line);
        std::cout<<line<<std::endl;
        if (line.length()>0){
            int flowRate=std::atoi(line.substr(line.find('=')+1,line.find(';')-line.find('=')-1).c_str());
            std::cout<<"Flow Rate: "<<flowRate<<std::endl;
            std::string valveName=line.substr(line.find(' ')+1,2);
            std::cout<<"Valve "<<valveName<<std::endl;
            int marker=line.find(',');
            Room newRoom;
            newRoom.name=valveName;
            newRoom.flowValue=flowRate;
            while (marker!=std::string::npos){
                std::string roomName=line.substr(marker-2,2);
                std::cout<<"Connection w/"<<roomName<<" found"<<std::endl;
                marker=line.find(',',marker+1);
                newRoom.connections.push_back(roomName);
            }
            std::string roomName=line.substr(line.size()-2,2);
            std::cout<<"Connection w/"<<roomName<<" found"<<std::endl;
            newRoom.connections.push_back(roomName);
            rooms[valveName]=newRoom;
            std::cout<<rooms[valveName]<<std::endl;
        }
    }
    for (std::map<std::string,Room>::iterator it=rooms.begin();it!=rooms.end();++it){
        for (std::map<std::string,Room>::iterator it2=rooms.begin();it2!=rooms.end();++it2){
            if (it->first==it2->first){
                rooms[it->first].paths[it2->first]=0;
                std::cout<<it->first<<"->"<<it2->first<<": 0"<<std::endl;
            } else {
                rooms[it->first].paths[it2->first]=findRoute(it->first,it2->first,{},0);
                std::cout<<it->first<<"->"<<it2->first<<": "<<rooms[it->first].paths[it2->first]<<std::endl;
            }
        }
    }
    explore("AA",{},0,0,0,"AA","0");
    std::cout<<"Max Flow Value: "<<maxFlow<<std::endl;

	return 0;
}