/*----
  signature: main: void -> int
  purpose: to remind you about C++ types of derived class objects

  compile using: (all on one line)
      g++ types-reminder.cpp Point.cpp ColorPoint.cpp
          -o types-reminder
  run using:
      ./types-reminder

  by: Sharon Tuttle
  last modified: 2022-11-28 - built from portion of W13-1
                              ColorPoint-play.cpp for W14-1 types
                              reminder
----*/

#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>
#include <typeinfo>
#include "Point.h"
#include "ColorPoint.h"
using namespace std;

int main()
{
    cout << boolalpha;

    // yes, you can have an array of type Point
    //    and put ColorPoint as well as Point objects
    //    into it (because a ColorPoint is also of type Point)

    cout << endl;
    Point my_quad[4];

    Point p_1(1, 1);
    Point p_2(2, 2);
    ColorPoint cp_1(3, 3, "green");
    ColorPoint cp_2(4, 4, "blue");

    my_quad[0] = p_1;
    my_quad[1] = p_2;
    my_quad[2] = cp_1;
    my_quad[3] = cp_2;

    cout << "Are you surprised by how the ColorPoint and"
         << endl << "   Point objects appear here?" << endl;
    
    for (int i=0; i < 4; i++)
    {
        cout << "my_quad[" << i << "]: "
             << my_quad[i].to_string() << endl;

        cout << typeid(my_quad[i]).name() << endl;
    }

    Point p1;
    ColorPoint cp1(1.1, 2.2, "onyx");
    p1 = cp1;

    cout << "calling p1.display(): " << endl;
    
    p1.display();

    cout << "calling cp1.display(): " << endl;

    cp1.display();

    // hopefully now demoing polymorphism,
    //    thanks to Point's  now-virtual display
    //    and to_string methods

    Point *point_ptrs[4];

    point_ptrs[0] = new Point(1, 1);
    point_ptrs[1] = new Point(2, 2);
    point_ptrs[2] = new ColorPoint(3, 3, "green");
    point_ptrs[3] = new ColorPoint(4, 4, "red");

    for (int i=0; i < 4; i++)
    {
       cout << endl;
       point_ptrs[i]->display();
       cout << point_ptrs[i]->to_string() << endl;
       cout << typeid(*(point_ptrs[i])).name() << endl;
    }

    // remember to free those dynamically-allocated
    //   Points and ColorPoints

    for (int i=0; i < 4; i++)
    {
        delete point_ptrs[i];
    }    

    Point *p2_ptr;
    ColorPoint *cp2_ptr = new ColorPoint(1.1, 2.2, "onyx");

    p2_ptr = cp2_ptr;

    cout << "calling p2_ptr->display(): " << endl;

    p2_ptr->display();

    delete cp2_ptr;
    
    cout << endl;
    return EXIT_SUCCESS;
}