/*----
  signature: main: void -> int
  purpose: playing with pointers and dynamic arrays
           and more!

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

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

int main()
{
    cout << boolalpha;

    PlayerChar angie("Angie", 10, 2.7, "tank", 15);

    PlayerChar  *player1_ptr;
    PlayerChar  *player2_ptr;
    PlayerChar  *player3_ptr;    

    // pointing to a static PlayerChar object is like
    //    you probably suspect

    player1_ptr = &angie;

    // NOTE the constructor call syntax when using
    //    new to dynamically allocate PlayerChar
    //    objects:

    // NOTE: with new, and a zero-argument constructor,
    //     OK to put () and OK to leave off the ()

    player2_ptr = new PlayerChar();
    player3_ptr = new PlayerChar("Jo", 11, 1.8, "wizard", 14);

    // BUT BE CAREFUL when you call a method of an object
    //   pointed to by a pointer --
    // . operator has HIGHER PRECEDENCE than *,
    //   you NEEEEEEEEED () to get the desired operation:

    cout << "(*player2_ptr).get_strength(): "
         << (*player2_ptr).get_strength()  << endl;

    // BUT this is very common!! To call a method of a
    //    pointed-to object! SO C++ provides some
    //    syntactic sugar for making this easier!
    //    -> operator
    //    ptr_to_obj->method() means
    //        call the method of the object ptr_to_obj
    //        points to
    //
    //    player2_ptr->get_strength()
    //    (*player2_ptr).get_strength()

    // does not work!!
    //cout << "*player2_ptr.get_strength(): "
    //     << *player2_ptr.get_strength()  << endl;

    // this DOES work also:

    cout << "player2_ptr->get_strength(): "
         << player2_ptr->get_strength()  << endl;

    PlayerChar *captain_ptr;
    captain_ptr = new PlayerChar("Ty", 8, 4.4, "support", 13);

    captain_ptr->set_name( captain_ptr->get_name() + "!" );

    cout << endl
         << captain_ptr->player_to_string() << endl;

    int num_widgets;
    double *widget_cost_array_ptr;

    cout << "Enter your number of widgets: ";
    cin >> num_widgets;

    widget_cost_array_ptr = new double[num_widgets];

    for (int i=0; i < num_widgets; i++)
    {
        cout << "enter next widget cost: ";
        cin >> widget_cost_array_ptr[i];
    }

    cout << "cost of 1st widget: "
         << widget_cost_array_ptr[0] << endl;

    // free the array using [] !!!!!

    delete [] widget_cost_array_ptr;

    // here's a dynamically-allocated array of PlayerChar

    PlayerChar *team;

    team = new PlayerChar[5];

    // this happens to call the 0-argument constructor
    //    for PlayerChar for each array element...

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

    delete [] team;

    // free all of your not-yet-deallocated
    ///    dynamically-allocated memory!

    // do NOT call delete for memory not allocated
    //    dynamically using new! Uncomment to see
    //    the resulting RUN-TIME error!!!
    //delete player1_ptr;
    
    delete player2_ptr;
    delete player3_ptr;
    delete captain_ptr;

    return EXIT_SUCCESS;
}