#pragma once

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


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


class Triangle : public Figure {
private:
    float a, b, c;

public:
    Triangle(float a, float b, float c) {
        this->a = a;
        this->b = b;
        this->c = c;
    }

    std::string Name() override {
        return "TRIANGLE";
    }
    float Perimeter() override {
        return a + b + c;
    }
    float Area() override {
        return sqrt((a+b+c)/2*((a+b+c)/2-a)*((a+b+c)/2-b)*((a+b+c)/2-c));
    }
};

class Rect : public Figure {
private:
    float width, height;

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

class Circle : public Figure {
private:
    float r;

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

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