<?php

class アニマルガール
{

    const とくいなんだねー = [
        'わーい',
        'すごーい'
    ];

    protected $おぼえてること = [];

    private final function __construct()
    {}

    protected static function サンドスター()
    {
        $class_path = get_called_class();
        return new $class_path();
    }

    public static function __callStatic($method, $arguments)
    {
        return ($instance ?? $instance = static::サンドスター())->$method();
    }

    public function __call($method, $arguments)
    {
        $this->おぼえてること[] = $method !== 'とくい' ? $method : (new class($arguments[0]) {

            const さいしょのおやくそく = '君は%sがとくいなフレンズなんだね！！';

            const すごいおやくそく = '%sができるフレンズなんだー！！';

            public $とくい = null;

            public $ちょっとまえ = アニマルガール::とくいなんだねー[0];

            public function __construct($とくい)
            {
                $this->とくい = $とくい;
            }

            public function __invoke()
            {
                return $this->とくい;
            }

            public function __toString()
            {
                $そうなんだー = sprintf($this->ちょっとまえ === アニマルガール::とくいなんだねー[1] ? self::すごいおやくそく : self::さいしょのおやくそく, $this->とくい);
                $this->ちょっとまえ = アニマルガール::とくいなんだねー[0];
                return $そうなんだー;
            }
        });

        return $this;
    }

    public function __invoke()
    {
        return $this->おぼえてること;
    }

    public function __toString()
    {
        $ちょっとまえ = null;
        foreach ($this->おぼえてること as $じゅんばん => $おぼえてること) {
            if (is_object($おぼえてること)) {
                $this->おぼえてること[$じゅんばん]->ちょっとまえ = $ちょっとまえ;
            } elseif (in_array($おぼえてること, アニマルガール::とくいなんだねー, true)) {
                $ちょっとまえ = $おぼえてること;
            }
        }
        return implode(\PHP_EOL, $this->おぼえてること) . \PHP_EOL;
    }
}

echo アニマルガール::わーい()->すごーい()->たのしー()->とくい('クソリプ');

echo アニマルガール::わーい()->とくい('クソリプ')->すごーい();

echo アニマルガール::すごーい()->とくい('クソリプ')->わーい()->たーのしー();

