<?php

namespace App\Controller;

use App\Entity\Bible;
use App\Entity\Note;
use App\Entity\Reference;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class ReferenceController extends AbstractController
{
    /**
     * @var EntityManagerInterface
     */
    public static EntityManagerInterface $emi;

    /**
     * Method to retrieve a Bible reference
     *
     * @param string $ref
     *
     * @return Reference
     */
    public static function retrieveBible($ref): Reference
    {
        $book = Bible::findBook($ref);
        $chapter = Bible::findChapter($ref);
        $passage = Bible::findVerse($ref);
        $bible = new Bible();
        $bible->setBook($book);
        $bible->setChapter($chapter);
        $label = null;

        if (is_array($passage)) {
            $passage_start = $passage[0];
            $passage_end = $passage[1];

            $bible = self::$emi->getRepository(Bible::class)->findRange($bible, [$passage_start, $passage_end]);
            $passage = "{$passage_start}-{$passage_end}";
            $label = "{$bible[0]->getLabel()}\n{$bible[0]->getChapter()}\n{$passage}";
        } elseif (is_int($passage)) {
            $bible = self::$emi->getRepository(Bible::class)->findBy(['book' => $book, 'chapter' => $chapter, 'verse' => $passage]);
            $label = "{$bible[0]->getLabel()}\n{$bible[0]->getChapter()}:{$passage}";
        } elseif ($passage === false) {
            $bible = self::$emi->getRepository(Bible::class)->findBy(['book' => $book, 'chapter' => $chapter], ['verse' => 'ASC']);
            $label = "{$bible[0]->getLabel()}\n{$bible[0]->getChapter()}";

            $passage = null;
        }

        if (is_array($bible)) {
            $text = [];
            foreach ($bible as $b) {
                $text[] = "{$b->getVerse()}. {$b->getContent()}";
            }
        } else {
            $text[] = "{$bible->getVerse()}. {$bible->getContent()}";
        }

        $reference = "{$book} {$chapter}".($passage === null ? '' : ":{$passage}");
        $ref = new Reference();
        $ref->setType('bible');
        $ref->setName($reference);
        $ref->setLabel($label);
        $ref->setContent("# {$reference}\n\n".implode("\n", $text)."<br/><br/>(ESV)");

        return $ref;
    }

    /**
     * Method to retrieve a creed
     *
     * @param string
     *
     * @return Reference
     */
    public static function retrieveCreed($ref): ?Reference
    {
        $ret = null;
        $r = self::$emi->getRepository(Reference::class)->findBy(['label' => $ref]);
        if ($r && count($r) > 0) {
            $ret = $r[0];
        }
        return $ret;
    }

    /**
     * Method to retrieve a Heidelberg Catechism reference
     *
     * @param Reference $ref
     *
     * @return Reference|array
     */
    public static function retrieveHC(Reference $ref): Reference|array
    {
        $r = self::$emi->getRepository(Reference::class)->findHeidelberg($ref->getLabel());
        
        if (!$r) {
            return new Reference();
        }
        return $r;
    }

    /**
     * Method to retrieve a Belgian Catechism reference
     *
     * @param Reference $ref
     *
     * @return Reference
     */
    public static function retrieveBC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => 'belgic', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    /**
     * Method to retrieve the Canon of Dort reference
     *
     * @param Reference $ref
     *
     * @return Reference
     */
    public static function retrieveCD($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => 'cd', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    /**
     * Method to retrieve a WSC reference
     *
     * @param Reference $ref
     *
     * @return Reference
     */
    public static function retrieveWSC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => $ref->getType(), 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    /**
     * Method to retrieve a WLC reference
     *
     * @param Reference $ref
     *
     * @return Reference
     */
    public static function retrieveWLC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => $ref->getType(), 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    /**
     * Method to retrieve a WCF reference
     *
     * @param Reference $ref
     *
     * @return Reference
     */
    public static function retrieveWCF($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => $ref->getType(), 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieveLBC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => 'lbc', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieveAGC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => 'agc', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieve39a($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => '39a', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieve1HC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => '1hc', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieve2HC($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => '2hc', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieveSD($ref): Reference
    {
        $r = self::$emi->getRepository(Reference::class)->findBy(['type' => 'sd', 'ndx' => $ref->getNdx()]);
        if (!$r) {
            return new Reference();
        }
        return $r[0];
    }

    public static function retrieveNote(?User $user): array
    {
        $notes = self::$emi->getRepository(Note::class)->findBy(['user' => $user], ['date' => 'DESC']);
        return $notes;
    }

    #[Route('/reference/{type}', name: 'app_reference_by_type', methods: ['GET'])]
    public function retrieveReferenceByType(string $type, EntityManagerInterface $emi): Response
    {
        $res = new Response();
        $data = $emi->getRepository(Reference::class)->findByType($type);

        $res->setContent(json_encode($data));
        return $res;
    }
}
