#include <iostream> // библиотека ввода-вывода
#include <vector> // библиотека векторов
#include <cmath> // библиотека для математических операций

using namespace std; // подключение стандартного пространства имён

int input_count();

class Point{
    int x; // координата x
    int y; // координата y

    public:

    void set_x(int _x){ this->x = _x; } // присваивание переданного значения для переменной x
    void set_y(int _y){ this->y = _y; } // присваивание переданного значения для переменной y

    int get_x(){ return this->x; } // возвращение значения x
    int get_y(){ return this->y; } // возвращение значения y
};

class Triangle{
    Point points[3]; // массив из 3 объектов класса Point
    float side_length, base_length; // сторона и основания треугольника
    float length[3]; // массив, хранящий длины сторон треугольника
    float square; // площадь треугольника
    
    public:

    void set_point(int _x, int _y, int index){ points[index].set_x(_x); points[index].set_y(_y); } // присваивание введённых значений точкам

    void input(){
        int x, y;

        cout << "\tInput points coordinates separated by a space\n\n";
        for (int i = 0; i < 3; i++){ // ввод координат точек треугольника
            cout << "\t\tInput " << i+1 << " point x & y coordinates: ";
            cin >> x >> y; // ввод 2 значений через пробел
            set_point(x, y, i); // вызов метода для передачи введённых значений
            cout << "\n";
        }
    }

    void output(){ // вывод координат
        cout << "\n\tOutput points coordinates\n\n";
        for (int i = 0; i < 3; i++){
            cout << "\t\t" << i+1 << " point\n";
            cout << "\t\tx: " << points[i].get_x() << "\n";
            cout << "\t\ty: " << points[i].get_y() << "\n\n";
        }
    }

    void get_length_side(){ // подсчёт длины сторон
        length[0] = sqrt(pow(points[1].get_x() - points[0].get_x(), 2) + pow(points[1].get_y() - points[0].get_y(), 2)); // B - A
        length[1] = sqrt(pow(points[2].get_x() - points[0].get_x(), 2) + pow(points[2].get_y() - points[0].get_y(), 2)); // C - A
        length[2] = sqrt(pow(points[2].get_x() - points[1].get_x(), 2) + pow(points[2].get_y() - points[1].get_y(), 2)); // C - B
        // подсчитываем длины сторон треугольника по формуле
    }

    bool is_triangle_isosceles(){ // проверка на равнобедренность
        get_length_side(); // сначала получаем длины сторон
        if (length[0] == length[1] || length[0] == length[2] || length[1] == length[2]){ // Если какие-то 2 стороны равны
            get_side_and_base_length(); // вычисляем, какя длина является основанием, а какая стороной
            return true; // возвращаем true
        }
        else { // иначе
            return false; // возвращаем false
        }
    }

    void get_side_and_base_length(){ // вычисление основания и стороны треугольника
        if (length[0] == length[1]){ // A = B
            side_length = length[0]; // Длинной треугольника будет A
            base_length = length[2]; // Основанием треугольника будет C
        }
        else if (length[0] == length[2]){ // A = C
            side_length = length[0]; // Длинной треугольника будет A
            base_length = length[1]; // Основанием треугольника будет B
        }
        else if (length[1] == length[2]){ // B = C
            side_length = length[1]; // Длинной треугольника будет B
            base_length = length[0]; // Основанием треугольника будет A
        }
    }

    float get_triangle_square(){
        square = (base_length / 4) * sqrt(4 * pow(side_length, 2) - pow(base_length, 2)); // вычисление площади

        return square; // возвращение полученного значения
    }
};

class TrianglesArray{
    vector <Triangle> triangles; // массив треугольников

    static int max_count; // статическая величина, задающая максимальное количество треугольников

    public:

    static void set_max_count(){ max_count = input_count(); } // установка максимального количества треугольников

    static int get_max_count() { return max_count; } // получение значения максимального количества треугольников

    TrianglesArray(){ // конструктор по умолчанию
        cout << "\nConstructor " << this << " initialized\n\n";
        input(max_count);
    }

    TrianglesArray(int count){ // конструктор с параметром
        cout << "\nConstructor " << this << " initialized\n\n";
        input(max_count);
    }
    // деструктор
    ~TrianglesArray(){ cout << "\nDestructor " << this << " initialized\n\n"; }

    void input(int count){ // ввод значений
        triangles.resize(max_count);
        for (int i = 0; i < max_count; i++){
            cout << "Input " << i+1 << " triangle\n\n";
            triangles[i].input();
        }
    }

    void output(){ // вывод значений
        cout << "\n\n";
        for (int i = 0; i < triangles.size(); i++){
            cout << "Output " << i+1 << " triangle\n";
            triangles[i].output();
        }
    }

    vector <int> get_isosceles_triangles(){ // получение равнобедренных треугольников (их индексов в массиве)
        vector <int> isosceles_triangles; // создание нового целочисленного массива

        for (int i = 0; i < triangles.size(); i++){ // цикл по массиву с объектами
            if (triangles[i].is_triangle_isosceles()){ // если текущий объект является равнобедренным треугольником
                isosceles_triangles.push_back(i); // заносим его индекс в целочисленный массив
            }
        }

        return isosceles_triangles; // возвращаем целочисленный массив с индексами
    }

    void output_isosceles_triangles(vector <int> isosceles_triangles){ // вывод индексов всех равнобедренных треугольников
        cout << "This triangles is isosceles: ";
        for (int i = 0; i < isosceles_triangles.size(); i++){
            cout << isosceles_triangles[i]+1 << " | ";
        }
        cout << "\n";
    }

    int get_max_square_index(vector <int> isosceles_triangles){ // получение индекса треугольника с максимальной площадью
        vector <float> squares; // массив для содержания значений площади объектов
        float max_square; // максимальная площадь
        int max_square_index; // индекс объекта с максимальной площадью

        squares.resize(isosceles_triangles.size()); // изменение размера нового массива для удобства присваивания

        for (int i = 0; i < isosceles_triangles.size(); i++){ // цикл по индексам равнобедренных треугольников
            squares[i] = triangles[isosceles_triangles[i]].get_triangle_square(); // получение площади всех равнобедренных треугольников и последующая их запись в новый массив 
        }

        // простой алгоритм для нахождения наибольшего значения
        max_square = squares[0];
        max_square_index = 0;
        for (int i = 0; i < squares.size(); i++){
            if (squares[i] > max_square){
                max_square = squares[i];
                max_square_index = i;
            }
        }

        return max_square_index; // возврат индекса треугольника с максимальной площадью
    }

    void operator++(){ // перегрузка оператора постинкремента
        cout << "Overload for postincrement operator\n"; // вывод сообщения о перегрузке
    }
};

enum ConstructorChoise{ // enum тут больше для понтов, но по факту тот же самый switch case, как в задании с файлами
    DEFAULT,
    WITH_PARAMETERS
};

int input_count(){ // так как мне ну очень лень писать эти строчки по 5 раз, я просто сделал здесь функцию, на 6 строке объявил прототип, чтобы компилятор не ругался
    int count = 0;

    while (count < 1){
        cout << "Input triangles count: ";
        cin >> count;
        cin.get();
        cout << "\n";
    }

    return count;
}

void operator<< (ostream& out, TrianglesArray& _triangle) //перегрузка оператора вывода
{
    _triangle.output(); // вызов функции вывода
}

int TrianglesArray::max_count = 2; // устанвока значения статической переменной по умолчанию

int main(){
    TrianglesArray* triangles_array;

    int count; // количество треугольников
    vector <int> isosceles_triangles; // массив равнобедренных треугольников
    int max_square_index; // индекс треугольника с наибольшей площадью

    int choise; // выбор типа конструктора
    char choose_count;

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

    cin >> choise;
    // выбор количества треугольников
    cout << "\nMax triangles count: " << TrianglesArray::get_max_count() << endl;
    cout << "Do you want change that value? y/n  ";
    cin >> choose_count;

    if (choose_count == 'y') TrianglesArray::set_max_count();

    switch (choise - 1) // отнимаем 1, так как отсчёт идёт с нуля
    {
    case ConstructorChoise::DEFAULT:
        cout << "\n" << "DEFAULT" << "\n\n";
        triangles_array = new TrianglesArray(); // инициализация объекта класса TrianglesArray
        break;
    case ConstructorChoise::WITH_PARAMETERS:
        cout << "\n" << "WITH_PARAMETERS" << "\n\n";
        triangles_array = new TrianglesArray(TrianglesArray::get_max_count()); // инициализация объекта класса TrianglesArray и передача введённого размера для количества журналов
        break;
    default:
        cout << "\n" << "Incorrect input." << "\n\n";
        return 0;
        break;
    }

    cout << (*triangles_array); // выводим значения треугольников через перегрузку оператора вывода

    isosceles_triangles = (*triangles_array).get_isosceles_triangles(); // находим индексы равнобедренных треугольников

    if (isosceles_triangles.size() < 1){ // если равнобедренных треугольников нет
        cout << "There are no isosceles triangles\n"; // выводим сообщение об их отсутствии
        delete triangles_array; // удаление динамического объекта
        return 0; // завершаем программу
    }

    (*triangles_array).output_isosceles_triangles(isosceles_triangles); // выводим индексы равнобедренных треугольников

    max_square_index = (*triangles_array).get_max_square_index(isosceles_triangles); // находим индекс треугольника с наибольшей площадью

    cout << "\nMax square's index: " << max_square_index+1 << "\n\n"; // выводим его

    (*triangles_array).operator++(); // вызов оператора постинкремента

    delete triangles_array; // удаление динамического объекта

    return 0; // конец
}