<?php /** @noinspection PhpUndefinedClassInspection */
/** @noinspection PhpDocSignatureInspection */
/** @noinspection PhpUnused */
/** @noinspection DuplicatedCode */
/** @noinspection PhpTranslationKeyInspection */

/**
 * Created by fediplan.
 * User: tom79
 * Date: 08/08/19
 * Time: 10:16
 */

namespace App\Controller;

use App\Form\ComposeType;
use App\Form\ConnectMastodonAccountFlow;
use App\Services\Mastodon_api;
use App\SocialEntity\Client;
use App\SocialEntity\Compose;
use App\SocialEntity\MastodonAccount;
use App\SocialEntity\PollOption;
use DateTime;
use DateTimeZone;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;


class FediPlanController extends AbstractController
{


    /**
     * @Route("/{_locale}",name="index", defaults={"_locale"="en"}, requirements={"_locale": "%allowed_language%"})
     */
    public function indexAction(Request $request, AuthorizationCheckerInterface $authorizationChecker, ConnectMastodonAccountFlow $flow, Mastodon_api $mastodon_api, TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher)
    {

        if ($authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY')) {
            $local = $request->getSession()->get('_locale');
            return $this->redirect($this->generateUrl('schedule', ['_locale' => $local]));
        }
        $client = new Client();
        $flow->bind($client);
        $form = $flow->createForm();
        $urlToMastodon = null;
        $client_id = null;
        $client_secret = null;
        if ($flow->isValid($form)) {
            if ($flow->getCurrentStep() == 1) {
                $host = $client->getHost();
                $result = $mastodon_api->getInstanceNodeInfo($host);
                //We currently only support Mastodon accounts
                if ($result != "MASTODON" && $result != "PLEROMA") {
                    $form->get('host')->addError(new FormError($translator->trans('error.instance.mastodon_only', [], 'fediplan', 'en')));
                } else {
                    $mastodon_api->set_url("https://" . $host);
                    $mastodon_api->set_scopes([]);
                    $createApp = $mastodon_api->create_app("FediPlan", [], '', "https://plan.fedilab.app");
                    if (isset($createApp['error'])) {
                        $form->get('host')->addError(new FormError($translator->trans('error.instance.mastodon_client_id', [], 'fediplan', 'en')));
                    } else {
                        // form for the next step
                        $mastodon_api->set_client($createApp['response']['client_id'], $createApp['response']['client_secret']);
                        $urlToMastodon = $mastodon_api->getAuthorizationUrl();
                        if (isset($createApp['error'])) {
                            $form->get('host')->addError(new FormError($translator->trans('error.instance.mastodon_oauth_url', [], 'fediplan', 'en')));
                        } else {
                            $flow->saveCurrentStepData($form);
                            $client_id = $createApp['response']['client_id'];
                            $client_secret = $createApp['response']['client_secret'];
                            $flow->nextStep();
                            $form = $flow->createForm();
                        }
                    }

                }
            } else if ($flow->getCurrentStep() == 2) {
                $host = $client->getHost();
                $code = $client->getCode();
                $mastodon_api->set_url("https://" . $client->getHost());
                $mastodon_api->set_scopes([]);
                $mastodon_api->set_client($client->getClientId(), $client->getClientSecret());
                $reply = $mastodon_api->loginAuthorization($code);
                if (isset($reply['error'])) {
                    $form->get('code')->addError(new FormError($translator->trans('error.instance.mastodon_token', [], 'fediplan', 'en')));
                } else {
                    $access_token = $reply['response']['access_token'];
                    $token_type = $reply['response']['token_type'];
                    $mastodon_api->set_url("https://" . $client->getHost());
                    $mastodon_api->set_token($access_token, $token_type);
                    $accountReply = $mastodon_api->accounts_verify_credentials();
                    if (isset($accountReply['error'])) {
                        $form->get('code')->addError(new FormError($translator->trans('error.instance.mastodon_account', [], 'fediplan', 'en')));
                    } else {
                        $Account = $mastodon_api->getSingleAccount($accountReply['response']);
                        $Account->setInstance($host);
                        $Account->setToken($token_type . " " . $access_token);
                        $token = new UsernamePasswordToken($Account, null, 'main', array('ROLE_USER'));
                        $this->get('security.token_storage')->setToken($token);
                        $event = new InteractiveLoginEvent($request, $token);
                        $eventDispatcher->dispatch($event, "security.interactive_login");
                        return $this->redirectToRoute('schedule');
                    }
                }
            }

        }

        return $this->render('fediplan/index.html.twig', [
            'form' => $form->createView(),
            'flow' => $flow,
            'urlToMastodon' => $urlToMastodon,
            'client_id' => $client_id,
            'client_secret' => $client_secret,
        ]);


    }


    /**
     * @Route("/{_locale}/schedule", name="schedule", defaults={"_locale"="en"}, requirements={"_locale": "%allowed_language%"})
     */
    public function schedule(Request $request, Mastodon_api $mastodon_api, TranslatorInterface $translator)
    {

        $compose = new Compose();

        $pollOption1 = new PollOption();
        $pollOption1->setTitle("");
        $compose->getPollOptions()->add($pollOption1);
        $pollOption2 = new PollOption();
        $pollOption2->setTitle("");
        $compose->getPollOptions()->add($pollOption2);
        $form = $this->createForm(ComposeType::class, $compose, ['user' => $this->getUser()]);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            /** @var $data Compose */
            $data = $form->getData();
            /* @var $user MastodonAccount */
            $user = $this->getUser();
            $mastodon_api->set_url("https://" . $user->getInstance());
            $token = explode(" ", $user->getToken())[1];
            $type = explode(" ", $user->getToken())[0];
            $mastodon_api->set_token($token, $type);
            $params = [];
            //Update media description and store their id
            foreach ($_POST as $key => $value) {
                if ($key != "compose") {

                    if (strpos($key, 'media_id_') !== false) {

                        $mediaId = $value;
                        $description = $_POST['media_description_' . $mediaId];
                        //update description if needed
                        if ($description != null && trim($description) != "") {
                            $mastodon_api->update_media($mediaId, ['description' => $description]);
                        }
                        $params['media_ids'][] = $mediaId;
                    }
                }
            }
            //Schedule status
            if ($data->getContentWarning()) {
                $params['spoiler_text'] = $data->getContentWarning();
            }
            if ($data->getContent()) {
                $params['status'] = $data->getContent();
            }
            if ($data->getVisibility()) {
                $params['visibility'] = $data->getVisibility();
            }
            $params['sensitive'] = ($data->getSensitive() == null || !$data->getSensitive()) ? false : true;

            $pollOptions = $data->getPollOptions();
            $pollExpiresAt = $data->getPollExpiresAt();
            $isPollMultiple = $data->isPollMultiple();
            if (count($pollOptions) > 0) {
                $count_correct_values = 0;
                foreach ($pollOptions as $po) {
                    /** @var $po PollOption */
                    if ($po->getTitle() != null && strlen(trim($po->getTitle())) > 0) {
                        $count_correct_values++;
                    }
                }

                if ($count_correct_values > 1) {
                    $params['poll']['options'] = [];
                    foreach ($pollOptions as $po) {
                        /** @var $po PollOption */
                        if ($po->getTitle() != null && strlen(trim($po->getTitle())) > 0) {
                            $params['poll']['options'][] = trim($po->getTitle());
                        }
                    }
                    $params['poll']['expires_in'] = $pollExpiresAt;
                    $params['poll']['multiple'] = $isPollMultiple;
                }
            }
            try {
                $date = new DateTime($data->getScheduledAt()->format("Y-m-d H:i"), new DateTimeZone($data->getTimeZone()));
                $date->setTimezone(new DateTimeZone("UTC"));
                $params['scheduled_at'] = $date->format(DateTime::ISO8601);
            } catch (Exception $e) {
            }
            $response = $mastodon_api->post_statuses($params);


            $session = $request->getSession();
            if (isset($response['error'])) {
                $session->getFlashBag()->add(
                    'Error',
                    $response['error_message']
                );
            } else {
                unset($compose);
                unset($form);
                $compose = new Compose();
                $pollOption1 = new PollOption();
                $pollOption1->setTitle("");
                $compose->getPollOptions()->add($pollOption1);
                $pollOption2 = new PollOption();
                $pollOption2->setTitle("");
                $compose->getPollOptions()->add($pollOption2);
                $session->getFlashBag()->add(
                    'Success',
                    $translator->trans('common.schedule_success', [], 'fediplan', 'en')
                );
                $form = $this->createForm(ComposeType::class, $compose, ['user' => $this->getUser()]);
            }
        }
        $user = $this->getUser();
        /** @var $user MastodonAccount */

        return $this->render("fediplan/schedule.html.twig", [
            'form' => $form->createView(),
            'instance' => $user->getInstance(),
            'token' => $user->getToken(),
        ]);

    }


    /**
     * @Route("/{_locale}/scheduled", name="scheduled", defaults={"_locale"="en"}, requirements={"_locale": "%allowed_language%"})
     */
    public function scheduled()
    {
        return $this->render("fediplan/scheduled.html.twig");
    }


    /**
     * @Route("/{_locale}/scheduled/messages/{max_id}",  options={"expose"=true}, name="load_more")
     */
    public function loadMoreAction(Mastodon_api $mastodon_api, string $max_id = null)
    {

        $user = $this->getUser();
        $mastodon_api->set_url("https://" . $user->getInstance());
        $token = explode(" ", $user->getToken())[1];
        $type = explode(" ", $user->getToken())[0];
        $mastodon_api->set_token($token, $type);
        $params = [];
        if ($max_id != null) {
            $params['max_id'] = $max_id;
        }
        $scheduled_reply = $mastodon_api->get_scheduled($params);
        $statuses = $mastodon_api->getScheduledStatuses($scheduled_reply['response'], $this->getUser());
        $data['max_id'] = $scheduled_reply['max_id'];
        $data['html'] = $this->renderView('fediplan/Ajax/layout.html.twig', ['statuses' => $statuses]);
        return new JsonResponse($data);
    }

    /**
     * @Route("/{_locale}/scheduled/delete/messages/{id}", options={"expose"=true}, name="delete_message", methods={"POST"}, defaults={"_locale"="en"}, requirements={"_locale": "%allowed_language%"})
     */
    public function deleteMessage(Mastodon_api $mastodon_api, string $id = null)
    {
        $user = $this->getUser();
        $mastodon_api->set_url("https://" . $user->getInstance());
        $token = explode(" ", $user->getToken())[1];
        $type = explode(" ", $user->getToken())[0];
        $mastodon_api->set_token($token, $type);
        $response = $mastodon_api->delete_scheduled($id);
        return new JsonResponse($response);
    }

    /**
     * @Route("/about",defaults={"_locale"="en"})
     * @Route("/{_locale}/about", name="about", defaults={"_locale":"en"}, requirements={"_locale": "%allowed_language%"})
     */
    public function about()
    {
        return $this->render("fediplan/about.html.twig");
    }

    /**
     * @Route("/logout", name="logout")
     */
    public function logout()
    {
        return $this->render("fediplan/index.html.twig");
    }

}