#pragma once

#include <string>
#include <cmath>
#include <memory>


class Figure {
 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;
    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 {};
}