<?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\MainBundle\Form\DataMapper;

use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\PostalCode;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\FormInterface;

/**
 * Add a data mapper to Address.
 *
 * If the address is incomplete, the data mapper returns null
 */
class AddressDataMapper implements DataMapperInterface
{
    /**
     * @param Address   $address
     * @param \Iterator $forms
     */
    public function mapDataToForms($address, \Traversable $forms)
    {
        if (null === $address) {
            return;
        }

        if (!$address instanceof Address) {
            throw new UnexpectedTypeException($address, Address::class);
        }

        foreach ($forms as $key => $form) {
            /* @var FormInterface $form */
            switch ($key) {
                case 'streetAddress1':
                    /* @phpstan-ignore-next-line */
                    $form->setData($address->getStreetAddress1());

                    break;

                case 'streetAddress2':
                    /* @phpstan-ignore-next-line */
                    $form->setData($address->getStreetAddress2());

                    break;

                case 'postCode':
                    $form->setData($address->getPostcode());

                    break;

                case 'validFrom':
                    $form->setData($address->getValidFrom());

                    break;

                case 'isNoAddress':
                    $form->setData($address->isNoAddress());

                    break;

                default:
                    break;
            }
        }
    }

    /**
     * @param \Iterator $forms
     * @param Address   $address
     */
    public function mapFormsToData(\Traversable $forms, &$address)
    {
        if (!$address instanceof Address) {
            $address = new Address();
        }

        $isNoAddress = false;

        foreach ($forms as $key => $form) {
            if ('isNoAddress' === $key) {
                $isNoAddress = $form->get('isNoAddress')->getData();
            }
        }

        foreach ($forms as $key => $form) {
            /* @var FormInterface $form */
            switch ($key) {
                case 'postCode':
                    if (!$form->getData() instanceof PostalCode && !$isNoAddress) {
                        $address = null;

                        return;
                    }
                    $address->setPostcode($form->getData());

                    break;

                case 'streetAddress1':
                    if (empty($form->getData()) && !$isNoAddress) {
                        $address = null;

                        return;
                    }
                    /* @phpstan-ignore-next-line */
                    $address->setStreetAddress1($form->getData());

                    break;

                case 'streetAddress2':
                    /* @phpstan-ignore-next-line */
                    $address->setStreetAddress2($form->getData());

                    break;

                case 'validFrom':
                    $address->setValidFrom($form->getData());

                    break;

                case 'isNoAddress':
                    $address->setIsNoAddress($form->getData());

                    break;

                default:
                    break;
            }
        }
    }
}
