<?php

namespace Fivable\Buildable\Builders;

use Fivable\Buildable\Models\BuildablePage;

class PageRenderer
{
    // The data for the Page Vue Component
    protected $pageData;
    // Page's Components
    protected $components = [];
    // Page's ComponentBuilders (for passing data to each Vue Component) grouped
    protected $componentBuilderGroups = [];
    // Scripts required by all of Page's Components, in order of execution
    protected $pageScripts = [];
    // Does this page have any google maps?
    public $hasMaps = false;

    /**
     * Instantiate a new PageRenderer
     * @param BuildablePage $buildablePage
     */
    public function __construct(BuildablePage $buildablePage)
    {
        $this->pageData = new \stdClass;
        $this->components = $buildablePage->components->sortBy('order')->keyBy('order');
        $this->pageData->componentCount = count($this->components);
        $this->pageData->innerPageNav = $buildablePage->inner_nav()->first();
        $this->build();
    }

    /**
     * Get PageRenderer ready for renderin'
     */
    public function build()
    {
        foreach ($this->components as $buildableComponent) {
            $componentBuilder = new ComponentBuilder($buildableComponent);

            if ($componentBuilder->hasMaps) {
                $this->hasMaps = true;
            }

            foreach ($componentBuilder->getComponentScripts() as $componentScriptGroup) {
                foreach ($componentScriptGroup as $executionOrder => $componentScript)
                $this->addPageScript($componentScript, $executionOrder);
            }
        }

        $this->make_groups($this->components);
    }

    /**
     * Add a BuildableComponent script to the PageRenderer with an optional execution order
     * @param string $scriptName
     * @param int $executionOrder
     */
    public function addPageScript(string $scriptName, int $executionOrder = 5)
    {
        $this->pageScripts[$executionOrder][] = $scriptName;
    }

    /**
     * Spit out any BuildableComponent scripts added during page-building
     * @return array
     */
    public function getPageScripts() : array
    {
        return $this->pageScripts;
    }

    /**
     * Spit out the grouped ComponentBuilders for this page
     * @return array
     */
    public function getComponentBuilderGroups() : array
    {
        return $this->componentBuilderGroups;
    }

    /**
     * Return object
     * @return string
     */
    public function getPageData() : string
    {
        return json_encode($this->pageData);
    }

    /**
     * Create an array of ComponentBuilder groups
     * @param $components
     */
    public function make_groups($components)
    {
        $group_num = 0;

        foreach($components as $order => $component) {
            $component_type = $component->slug;
            $component->index = $order;

            // If there is a row before the current row
            if(!empty($this->componentBuilderGroups[$group_num]['rows'])) {
                
                $firstComponentInCurrentRow = $this->componentBuilderGroups[$group_num]['rows'][0]->getComponent();

                // If the previous and current row have the same row type, add the row
                // to the same group
                if($firstComponentInCurrentRow->slug == $component_type && $component->is_grouped && $firstComponentInCurrentRow->is_grouped) {
                    $this->componentBuilderGroups[$group_num]['rows'][] = new ComponentBuilder($component);
                }
                // The previous and current row don't have the same row type, so
                // add the current row to a new group
                else {
                    $group_num++;
                    $this->componentBuilderGroups[$group_num]["slug"] = $component_type;
                    $this->componentBuilderGroups[$group_num]['rows'][] = new ComponentBuilder($component);
                }
            }

            // There is no row before the current row, so add current row to the
            // first group
            else {
                $group_num++;
                $this->componentBuilderGroups[$group_num]["slug"] = $component_type;
                $this->componentBuilderGroups[$group_num]['rows'][] = new ComponentBuilder($component);
            }
        }

        foreach ($this->componentBuilderGroups as &$componentBuilderGroup) {
            $angledTop = $angledBottom = false;
            foreach ($componentBuilderGroup['rows'] as $component) {
                if ($component->hasAngledTop()) {
                    $angledTop = true;
                }
                if ($component->hasAngledBottom()) {
                    $angledBottom = true;
                }
            }
            $componentBuilderGroup['angledTop'] = $angledTop;
            $componentBuilderGroup['angledBottom'] = $angledBottom;
        }
    }

    /**
     * Checks if Font Family string is in the buildable-fonts.json
     *
     * @param string $font_family
     */
    public static function isGoogleFont($font_family) : bool
    {
      $json_contents = file_get_contents(resource_path('assets/vendor/buildable/buildable-fonts.json'));

      return !!strpos($json_contents, $font_family);
    }
}
