/*----
    implementation file for class: Team

    A Team is a collection of PlayerChar instances.
    The user specifies its name and size (if they would like),
        and they can specify what players make up that team.

    NOW adding destructor, copy constructor,
        and overloaded assignment operator
        (the "big 3"!)

    by: Sharon Tuttle
    last modified: 2022-10-13
----*/

#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>
#include "PlayerChar.h"
#include "Team.h"
using namespace std;

/*---
    constructors
---*/

/*---
    Decided that a team's size will be DEFAULT_SIZE
        if no size is specified by the constructor
---*/

Team::Team()
{
    name = "";
    size = DEFAULT_SIZE;
    players = new PlayerChar[size];
}


Team::Team(string init_name, int desired_size)
{
    name = init_name;
    size = desired_size;
    players = new PlayerChar[size];
}

/*---
    destructor

    here, I want to free the dynamic players
        array's memory
---*/

Team::~Team()
{
    // reminder: keyword this is a pointer to
    //    the calling object

    cout << "called Team " << name << "'s destructor" << endl
         << "   for Team object at address: " << this << endl;

    delete [] players;
}

/*---
    copy constructor 

    job: is to construct a complete, INDEPENDENT copy
        of its argument
---*/

Team::Team(const Team& a_team)
{
    cout << "called copy constructor" << endl;

    name = a_team.name;
    size = a_team.size;

    players = new PlayerChar[size];

    for (int i=0; i < size; i++)
    {
        players[i] = a_team.players[i];
    }
}

Team& Team::operator=(const Team& rhs)
{
    cout << "called overloaded assignment operator" << endl;

    // NOTE: this could be more elegantly arranged!

    // checking for self-assignment

    if (this == &rhs)
    {
        return *this; // remember, return ends a method
    }

    // only get here if NOT self-assignment

    // deallocate any dynamic memory used by the LHS

    delete [] players;

    // allocate memory to hold the new version of
    //    dynamic data fields to be copied

    players = new PlayerChar[rhs.size];

    // copy the values from the rhs into the lhs

    name = rhs.name;
    size = rhs.size;

    for (int i=0; i < size; i++)
    {
        players[i] = rhs.players[i];
    }

    // be sure to return the LHS's value
    //    (because that's what assignment returns
    //    in C++)

    return *this;
}

/*---
    accessors
---*/

string Team::get_name() const
{
    return name;
}

int Team::get_size() const
{
    return size;
}

/*---
    positions are 1-based (positions are from 1 to size)
---*/

PlayerChar Team::get_player(int position) const
{
    // yes I SHOULD come back and throw an exception
    //    if the user gives a position outside of
    //    [1, size] !!!!!!!!!

    // location position is at index (position - 1) 

    return players[position - 1];
}

/*---
    mutators
---*/

void Team::set_name(string new_name)
{
    name = new_name;
}

void Team::set_player(PlayerChar a_player, int position)
{
    // yes I SHOULD come back and throw an exception
    //    if the user gives a position outside of
    //    [1, size] !!!!!!!!!

    // location position is at index (position - 1) 

    players[position - 1] = a_player;
}

/*---
    other methods
---*/

/*---
    signature: display: void -> void
    purpose: expects nothing, has the side-effect of
         printing to the screen the team's name,
         size, and player details, and returns nothing
    tests:
        for:
        Team ex_team1;

        ex_team1.display();

        should print to the screen:

Team: , size: 4
PlayerChar(, 5, 0.000000, , 20)
PlayerChar(, 5, 0.000000, , 20)
PlayerChar(, 5, 0.000000, , 20) 
PlayerChar(, 5, 0.000000, , 20)

        for:
        Team ex_team2("example2", 2);
        PlayerChar angie("Angie", 10, 2.7, "tank", 15);
        PlayerChar sven("Sven", 5, 3.1, "support", 14);
        ex_team2.set_player(angie, 1);
        ex_team2.set_player(sven, 2);

        ex_team2.display()

        should print to the screen:

Team: example2, size: 2
PlayerChar(Angie, 10, 2.700000, tank, 15)
PlayerChar(Sven, 5, 3.100000, support, 14)

---*/

void Team::display() const
{
    cout << endl;
    cout << "Team: " << name << ", size: " << size << endl;
    
    // display each player's info

    for (int i=0; i < size; i++)
    {
        cout << players[i].player_to_string() << endl;
    }
    cout << endl;
}

/*---
    signature: is_bigger_than: Team -> bool
    purpose: expects a Team object, and returns
        whether the calling team has more team
        members than the given team

    tests:
        Team team1("Team 1", 2);
        Team team2("Team 2", 3);

        team1.is_bigger_than(team_2) == false
        team2.is_bigger_than(team_1) == true
        team1.is_bigger_than(team_1) == false
---*/

bool Team::is_bigger_than(Team another_team) const
{
    return (size > another_team.size);
}