#pragma once
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::cerr;
using std::endl;
using std::string;

const bool DEBUGMODE = false; // used to turn debugging output on/off

// representation of a single item within a linked list
struct ItemRank {
   int rank;            // positive integer rank
   string description;  // text description of item
   ItemRank* next; // pointer to the item after/behind this item (closer to the back)
   ItemRank* prev; // pointer to the item ahead/before this item (closer to the front)
};

// representation of a list of items
struct ItemList {
   ItemRank* front; // the first item in line
   ItemRank* back; // the last item in line
   int size; // number of items in the list
};

// delete all the allocated items in a list then re-initialize it
void deallocate(ItemList &rankings);

// load item rankings from the named file, store in rankings,
// return true if successful, false otherwise
bool readRankings(string filename, ItemList &rankings);

// initialize a list as empty
void initList(ItemList &rankings);

// insert the item at the back of the rankings list
// return true if successful, false otherwise
bool insertBack(ItemList &rankings, ItemRank* item);

// remove the front item from the rankings list
// return the pointer to it (null if list was empty)
ItemRank* removeFront(ItemList &rankings);

// return a pointer to the nth item in the list, null if N not valid
ItemRank* getNthItem(ItemList rankings, int N);

// return true iff descript is a valid item description
// (i.e. contains at least one non-whitespace character)
bool validDescription(string descript);

// run a head-to-head matchup
//     - pick distinct pair of items
//     - present user with choice, get valid response
//     - update rankings based on response
// return true iff the matchup is successful
bool runMatchup(ItemList &rankings);

// write rankings to a file
// return true iff successful
bool writeRankings(string filename, ItemList rankings);

// calculate and return new rank for X based on current ranks for X and Y
//    and score from X's perspective: 1=X win, 0.5=draw, 0=Y win
// return unchanged RankX in the event of an invalid parameter
int calcNewRank(int RankX, int RankY, float score);

// present the user with a choice between items X and Y
// return 1 if they choose X
//        0 if they choose Y
//        0.5 if it's a draw
// (repeat until they make a valid choice)
float getChoice(ItemRank* X, ItemRank* Y);

// remove rankings from the two sorted source lists, merging them into the destination list
bool merge(ItemList &source1, ItemList &source2, ItemList &destination);

// sort the rankings from lowest rank to highest
void msortRanks(ItemList &rankings);

