#include <iostream>
#include <vector>

using namespace std;

class Point{
    int x, y;

    public:

    Point(){ // конструктор без параметров
        cout << "Constructor " << this << " initialized.\n"; // вывод информации о инициализации конструктора
    }

    Point(int _x, int _y){ // конструктор с параметрами
        cout << "Constructor " << this << " initialized.\n"; // вывод информации о инициализации конструктора
        this->x = _x; this->y = _y; // присваивание аргументов функции в значения переменных класса
    }

    void set_coordinates(){ // сеттер (установка значений переменных класса)
        int _x, _y;
        cout << " input x y coordinates with space: "; cin >> _x >> _y;
        this->x = _x; this->y = _y;
    }
    // геттеры (получение значений переменных класса)
    int get_x(){ return this->x; }
    int get_y(){ return this->y; }

    int operator-(Point& b) { // перегрузка оператора вычитания
        return (this->x - b.x) * (this->x - b.x) + (this->y - b.y) * (this->y - b.y); // возвращение значения
        // в выражении сверху от переменных
    }

    ~Point(){ // деструктор
        cout << "Destructor " << this << " initialized.\n"; // вывод информации о инициализации деструктора
    }
};
// массив с определёнными 
enum class e_types {
    rect,
    square,
    rhombus,
    trapezoid,
    same_shape,
    parallelogram
};

e_types get_typeof_shape(Point a, Point b, Point c, Point d) {
    // получение растояния между точками через перегрузку оператора вычитания
    int AB = a - b;
    int BC = b - c;
    int CD = c - d;
    int DA = d - a;
    int AC = a - c;
    int BD = b - d;

    if (AB == CD && BC == DA)
    {
        if (AB == BC && AC == BD)
            return e_types::square;

        if (AB == BC && AC != BD)
            return e_types::rhombus;

        if (AB != CD && AC == BD)
            return e_types::rect;

        if (AB != CD && AC != BD)
            return e_types::parallelogram;
    }
    else
        if (((a.get_x() - b.get_x()) * (c.get_y() - d.get_y()) == (a.get_y() - b.get_y()) * (c.get_x() - d.get_x())) || 
            ((a.get_x() - d.get_x()) * (b.get_y() - c.get_y()) == (a.get_y() - d.get_y()) * (b.get_x() - c.get_x())))
            return e_types::trapezoid;
        else
            return e_types::same_shape;
}
 
enum UserChoise { 
    DEFAULT,
    WITH_PARAMETERS
};

int main() {
    int choise; // выбор типа конструктора
    e_types *result;
    result = new e_types;

    cout << "Please, choose constructor's type:" << "\n";
    cout << "1. Default constructor (without parameters)." << "\n";
    cout << "2. Constructor with parameters." << "\n\n";

    cin >> choise;

    switch (choise - 1) // отнимаем 1, так как отсчёт идёт с нуля
    {
    case UserChoise::DEFAULT:
    {
        cout << "\n" << "Default constructor." << "\n\n";
        Point *points[4];

        for (int i = 0; i < 4; i++){ 
            cout << i+1 << " point -"; 
            points[i] = new Point();
            (*points[i]).set_coordinates(); 
        }
    
        *result = get_typeof_shape(*points[0], *points[1], *points[2], *points[3]);

        delete points;

        break;
    }
    case UserChoise::WITH_PARAMETERS:
    {
        cout << "\n" << "Constructor with parameters." << "\n\n";
        Point *points[4];

        for (int i = 0; i < 4; i++){
            int x, y;
            cout << i+1 << " point -" << " input x y coordinates with space: "; cin >> x >> y;
            points[i] = new Point(x, y);
        }

        cout << "\n";

        *result = get_typeof_shape(*points[0], *points[1], *points[2], *points[3]);

        delete points;

        break;
    }
    default:
        cout << "\n" << "Incorrect input." << "\n\n";
        return 0;
        break;
    }


    cout << "\nDefined type of shape: ";
    switch (*result)
    {
    case e_types::same_shape:
        cout << "arbitrary quadrangle" << endl;
        break;
    case e_types::rect:
        cout << "rect" << endl; //прямоугол
        break;
    case e_types::rhombus:
        cout << "rhombus" << endl;//ромб
        break;
    case e_types::square:
        cout << "square" << endl;
        break;
    case e_types::trapezoid:
        cout << "trapezoid" << endl;//трапеция
        break;
    case e_types::parallelogram:
        cout << "parallelogram" << endl;//parallelogram
        break;
    }

    delete result;

    cout << "\n";
}