#pragma once

#include <sstream>
#include <cmath>


class Figure {
    //private:
    //    string Name;
    //    float Perimeter;
    //    float Area;
    public:
        virtual std::string Name() = 0;
        virtual float Perimeter() = 0;
        virtual float Area() = 0;
};


class Triangle : public Figure {
    private:
        std::string name;
        float perimeter;
        float area;

    public:
        Triangle(float a, float b, float c){
            this->name = "TRIANGLE";
            this->perimeter = a + b + c;
            this->area = sqrt((a + b + c)/2 * ((a + b + c)/2 - a) * ((a + b + c)/2 - b) * ((a + b + c)/2 - c));
        }

        std::string Name() override {
            return this->name;
        }
        float Perimeter() override {
            return this->perimeter;
        }
        float Area() override {
            return this->area;
        }
};

class Rect : public Figure {
    private:
        std::string name;
        float perimeter;
        float area;

    public:
        Rect(float width, float height){
            this->name = "RECTANGLE";
            this->perimeter = 2 * (width + height);
            this->area = width * height;
        }
        std::string Name() override {
            return this->name;
        }
        float Perimeter() override {
            return this->perimeter;
        }
        float Area() override {
            return this->area;
        }
};

class Circle : public Figure {
    private:
        std::string name;
        float perimeter;
        float area;

    public:
        explicit Circle(float r){
            this->name = "CIRCLE";
            this->perimeter = 2 * 3.14 * r;
            this->area = 3.14 * r * r;
        }
        std::string Name() override {
            return this->name;
        }
        float Perimeter() override {
            return this->perimeter;
        }
        float Area() override {
            return this->area;
        }
};

std::shared_ptr<Figure> CreateFigure(std::istringstream &is){
    std::string type;
    float width, height, a, b, c, r;
    is >> type;
    is >> std::ws;
    if (type == "RECT"){
        is >> width >> height;
        return std::shared_ptr<Figure>{new Rect(width, height)};
    }
    else if (type == "CIRCLE"){
        is >> r;
        return std::shared_ptr<Figure>{new Circle(r)};
    }
    else if (type == "TRIANGLE"){
        is >> a >> b >> c;
        return std::shared_ptr<Figure>{new Triangle(a, b, c)};
    }
    return {};
}