<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\PersonBundle\Doctrine\DQL;

use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;

/**
 * USAGE GET_ADDRESS_<part>(person.id, :date, 'postcode') where part
 * should be replace by the part of the address.
 *
 * This function return the current address part at the given date, for the
 * given person (identified by his id)
 *
 * The aim of this function is to be used within reports
 */
abstract class AddressPart extends FunctionNode
{
    public $fields = [
        'address_id',
        'streetaddress1',
        'streetaddress2',
        'validfrom',
        'postcode_label',
        'postcode_code',
        'postcode_id',
        'country_name',
        'country_code',
        'country_id',
    ];

    private \Doctrine\ORM\Query\AST\Node|string|null $date = null;

    /**
     * @var \Doctrine\ORM\Query\AST\Node
     */
    private $part;

    private ?\Doctrine\ORM\Query\AST\PathExpression $pid = null;

    /**
     * return the part of the address.
     *
     * Should be one value of the "public" amongst
     * 'address_id', 'streetaddress1',
     * 'streetaddress2', 'validfrom',  'postcode_label',  'postcode_code',
     * 'postcode_id', 'country_name', 'country_code',  'country_id', 'isnoaddress'
     *
     * @return string
     */
    abstract public function getPart();

    public function getSql(SqlWalker $sqlWalker)
    {
        return sprintf(
            'get_last_address_%s(%s, %s)',
            $this->getPart(),
            $this->pid->dispatch($sqlWalker),
            $this->date->dispatch($sqlWalker)
        );
    }

    public function parse(Parser $parser)
    {
        $a = $parser->match(\Doctrine\ORM\Query\TokenType::T_IDENTIFIER);
        $parser->match(\Doctrine\ORM\Query\TokenType::T_OPEN_PARENTHESIS);
        // person id
        $this->pid = $parser->SingleValuedPathExpression();
        $parser->match(\Doctrine\ORM\Query\TokenType::T_COMMA);
        // date
        $this->date = $parser->ArithmeticPrimary();
        $parser->match(\Doctrine\ORM\Query\TokenType::T_CLOSE_PARENTHESIS);
    }
}
