#include <iostream>
#include <list>
#include <memory>

class Animal {
  public:
    Animal(){}
  virtual void DoSound() = 0;
  virtual int GetWeight() = 0;
  virtual ~Animal() {};
};

class House : public Animal {
public:
  std::list<std::unique_ptr<Animal>> obsah;
  House() {}
  House(std::list<std::unique_ptr<Animal>> &&obsah) : obsah(std::move(obsah)) {}
  int GetWeight()
  {
    size_t result = 0;
    for (auto&& x : obsah)
    {
      result += x->GetWeight();
    }
    return result;
  }
  void DoSound()
  {
    std::cout << "Sounds of house: [" << std::endl;
    for (auto&& x : obsah)
    {
      x->DoSound();
    }
    std::cout << "]" << std::endl;
  }
};

class Lion : public Animal {
public:
  std::unique_ptr<Animal> food;
  Lion() {}
  Lion(std::unique_ptr<Animal> && f) {
      food = std::move(f);
  }

  void DoSound(){
    std:: cout << "Meow, snedl jsem: [";
    food->DoSound();
    std::cout << " ]" << std::endl;
  }

  int GetWeight(){
    return 100 + food->GetWeight();
  }

};
class Dog : public Animal {
  public:
  void DoSound(){
    std::cout << "Bark" << std::endl;
  }
  int GetWeight() {
    return 10;
  }
  ~Dog() {
    std::cout << "Pes odchazi" << std::endl;
  }
};


class Tiger : public Animal {
  public:
  int Weight;
  Tiger(int weight) {
    Weight = weight;
  }
  void DoSound(){
    std::cout << "Grrr x" << Weight << std::endl;
  }
  int GetWeight() { 
    return 20;
  }

  ~Tiger() {
    std::cout << "Tygr odchazi" << std::endl;
  }
};

using Animals = std::list<std::unique_ptr<Animal>>;

int main(){
  std::list<std::unique_ptr<Animal>> zoo;
  zoo.push_back(std::make_unique<Dog>());
  zoo.push_back(std::make_unique<Tiger>(10));
  zoo.push_back(std::make_unique<Tiger>(20));
  zoo.push_back(std::make_unique<Lion>(std::make_unique<Dog>()));
  zoo.push_back(std::make_unique<House>());
  House* h = dynamic_cast<House*>(zoo.back().get());
  h->obsah.push_back(std::make_unique<Tiger>(10));
  

  /*zoo.push_back(std::make_unique<House>
  (std::list<std::unique_ptr<Animal>>{std::make_unique<Dog>()}));*/
  
  //std::list<int> a{1,2,3};
  
  for(auto && x :zoo){
    x->DoSound();
  }
  
  int sum_weight = 0;
  for(auto && a : zoo)
    sum_weight += a->GetWeight();
  std::cout << sum_weight << std::endl;

  
}

int main2() {
  Dog d;
  d.DoSound();

  Animal* p;
  p = &d;

  p -> DoSound();
  return 0;
  
}
