#pragma once

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

class Figure {
 public:
    Figure() = default;

    ~Figure() = default;

    virtual std::string Name() = 0;

    virtual float Perimeter() = 0;

    virtual float Area() = 0;
};

class Triangle : public Figure {
 public:
    Triangle(float a, float b, float c) : a(a), b(b), c(c) {}

    std::string Name() override { return "TRIANGLE"; }

    float Perimeter() override {
        return  a + b + c;
    }

    float Area() override {
        float s = (this->a + this->b + this->c) / 2;
        return std::sqrt(s * (s - this->a) * (s - this->b) * (s - this->c));
    }

 private:
    float a, b, c;
};

class Rect : public Figure {
 public:
    Rect(float width, float height) : width(width), height(height) {}

    std::string Name() override { return "RECT"; }

    float Perimeter() override {
        return width * 2 + height * 2;
    }

    float Area() override {
        return width * height;
    }

 private:
    float width, height;
};

class Circle : public Figure {
 public:
    explicit Circle(float radius) : radius(radius) {}

    std::string Name() override { return "CIRCLE"; }

    float Perimeter() override {
        return 6.28 * radius;
    }

    float Area() override {
        return 3.14 * radius * radius;
    }

 private:
    float radius;
};


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