<?php
/**
 * This file is part of the DATAtourisme project.
 *
 *  @author Conjecto <contact@conjecto.com>
 *
 * For the full copyright and license information, please view the LICENSE file that was distributed with this source code.
 */

namespace Datatourisme\Api\Schema\Compiler;

class FieldCompiler extends AbstractCompiler
{
    public function compile(): string
    {
        $this->content = '';
        foreach ($this->schema['fields'] as $field => $def) {
            $this->consumeField($field, $def);
            $this->consumeFilterField($field, $def);
            $this->consumeSortField($field, $def);
        }

        return $this->content;
    }

    /**
     * @param $name
     * @param $def
     */
    protected function consumeField($name, $def)
    {
        if (is_array($def['type'])) {
            $type = 'new ListType(new Type_'.SchemaCompiler::normalize($def['type']).'())';
        } elseif (isset($this->schema['types'][$def['type']])) {
            $type = 'new ListType(new Type_'.SchemaCompiler::normalize($def['type']).'())';
        } else {
            $uri = $this->prefixMap->expandUri($def['type']);
            $type = 'new ListType(new \\'.$this->schemaCompiler->resolveType($uri).'())';
        }

        $className = 'Field_'.SchemaCompiler::normalize($name);
        $this->content .= $this->render('field.twig', $className, [
            'type' => $type,
            'uri' => $this->prefixMap->expandUri($name),
            'range' => $this->getRangeUri($def),
            'name' => SchemaCompiler::normalize($name),
            'description' => $def['description'],
        ]);
    }

    /**
     * @param $name
     * @param $def
     */
    protected function consumeFilterField($name, $def)
    {
        if (is_array($def['type'])) {
            $type = 'new FilterType_'.SchemaCompiler::normalize($def['type']).'()';
        } elseif (isset($this->schema['types'][$def['type']])) {
            $type = 'new FilterType_'.SchemaCompiler::normalize($def['type']).'()';
        } else {
            $type = 'new FilterType()';
        }
        $className = 'FilterField_'.SchemaCompiler::normalize($name);
        $this->content .= $this->render('field.twig', $className, [
            'type' => $type,
            'uri' => $this->prefixMap->expandUri($name),
            'range' => $this->getRangeUri($def),
            'name' => SchemaCompiler::normalize($name),
            'description' => $def['description'],
        ]);
    }

    /**
     * @param $name
     * @param $def
     */
    protected function consumeSortField($name, $def)
    {
        if (is_array($def['type'])) {
            $type = 'new SortType_'.SchemaCompiler::normalize($def['type']).'()';
        } elseif (isset($this->schema['types'][$def['type']])) {
            $type = 'new SortType_'.SchemaCompiler::normalize($def['type']).'()';
        } else {
            $type = 'new SortType()';
        }

        $className = 'SortField_'.SchemaCompiler::normalize($name);
        $this->content .= $this->render('field.twig', $className, [
            'type' => $type,
            'uri' => $this->prefixMap->expandUri($name),
            'range' => $this->getRangeUri($def),
            'name' => SchemaCompiler::normalize($name),
            'description' => $def['description'],
        ]);
    }

    /**
     * @param $def
     *
     * @return null|string
     */
    private function getRangeUri($def)
    {
        if ($def['type']) {
            $uri = is_array($def['type']) ? $def['type'][0] : $def['type'];

            return $this->prefixMap->expandUri($uri);
        }

        return null;
    }
}
