<?php
namespace Webkul\DamBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Webkul\DamBundle\Entity\Asset;
use Oro\Bundle\SecurityBundle\Annotation\AclAncestor;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Webkul\DamBundle\Entity\AssetCategoryTranslation;
use Webkul\DamBundle\Listener\ClassDefinationForCompatibility;

$versionCompatiblility = new ClassDefinationForCompatibility();
$versionCompatiblility->createClassAliases();
/**
 * Externel Api Controller
 *
 * @author    Aman Srivastav <aman.srivastava462@webkul.com>
 * @copyright 2019 Webkul Soft Pvt. Ltd (https://webkul.com/)
 */

class ExternelApiController extends Controller
{
    /**
     * webService for get list of asset
     * @param Request $request
     * @return jsonResponse with pagiation
     */
    public function listAssetAction(Request $request)
    {
        $page = $request->query->get('page');
        $limit = $request->query->get('limit');
        $currentPage = isset($page) ? $page : 1;
        $currentLimit = isset($limit) ? $limit : 10;

        $assetQuery = $this->get('webkul_dam.repository.asset')
                           ->createQueryBuilder('a')
                           ->orderBy('a.createdAt', 'DESC')
                           ->getQuery();

        $paginator = $this->paginate($assetQuery, $currentPage, $currentLimit);

        $asset = $paginator->getIterator()->getArrayCopy();
        
        $assets = [];

        foreach ($asset as $as) {
            $assets[] = [
                            "id" => $as->getId(),
                            "code" => $as->getCode()
                        ];
        }

        return new JsonResponse($assets);
    }

    /**
     * get paginate
     * @param $dql
     * @param $page
     * @param $limit
     * @return $paginator
     */
    public function paginate($dql, $page, $limit)
    {
        $paginator = new Paginator($dql);
      

        $paginator->getQuery()
            ->setFirstResult($limit * ($page - 1)) // Offset
            ->setMaxResults($limit); // Limit

        return $paginator;
    }

    public function getAssetApiAction($identifier)
    {
        $asset = $this->get('webkul_dam.repository.asset')->getSingleArrayResultByCode($identifier);
        $connectorService = $this->get('dam.connector.service');
        if ($asset['code']) {
            $tags = $connectorService->getRelatedTagsOfAssets($asset['code']);
            if (!empty($tags)) {
                $asset['tag'] = $tags;
            }
            $categories = $connectorService->getRelatedCategoriesOfAssets($asset['code']);
            if (!empty($categories)) {
                $asset['category'] = $categories;
            }
        }
       
        if (!$asset) {
            return new JsonResponse([], Response::HTTP_NOT_FOUND);
        }
        
        $router = $this->get('router');
        if (isset($asset['medias']) && !empty($asset['medias'])) {
            $medias = [];
            foreach ($asset['medias'] as $media) {
                $url = $router->generate('webkuldam_media_download', [
                                                                        'identifier' => rawurlencode($media['filePath'])
                                                                    ], UrlGeneratorInterface::ABSOLUTE_URL);
                $updatedMedia = [
                                    "filePath" => $media['filePath'],
                                    "url" => $url
                    
                                ];
                                                           
                $medias[] = $updatedMedia;
            }

            unset($asset['medias']);
            $asset['medias'] = $medias;
        }

        return new JsonResponse($asset);
    }
    /**
    * Add Assets
    * @param Request $request
    * @return jsonResponse added Asset
    */
    public function addAssetAction(Request $request)
    {
        $data = $this->getDecodedContent($request->getContent());
        $result = [];
        if (isset($data['code'])) {
            $repo = $this->container->get('webkul_dam.repository.asset')->findOneByCode($data['code']);

            if (!$repo) {
                $connectorService = $this->get('dam.connector.service');
                if (isset($data['media'])) {
                    foreach ($data['media'] as $mediaKey => $media) {
                        $filePath = $connectorService->changeUrlToContent($media, $data['code'], $mediaKey);
                        if ($filePath) {
                            $data['media'][$mediaKey] = $filePath;
                        }
                    }
                }
        
                if (isset($data['tags'])) {
                    $data['tags'] = implode(' & ', $data['tags']);
                }
        
                if (isset($data['categories'])) {
                    $data['categories'] = implode(' & ', $data['categories']);
                }
        
                // $fst->put($filePath, $data);
                $factory = $this->get('webkul_dam.factory.asset');
                $updater = $this->get('webkul_dam.updater.asset');
                $saver = $this->get('webkul_dam.saver.asset');
                
                $asset = $factory->create();
                $updater = $updater->update($asset, $data);
                $saver = $saver->save($asset);
                $result = $this->objectToIndex($asset);
            } else {
                $result['error'] = "Asset with this code is already exist !!";
            }
        } else {
            $result['error'] = "Some error occured!! Code is not defined.";
        }

        return !isset($result['error']) ? new JsonResponse($result)
                                        : new JsonResponse(
                                            $result,
                                            RESPONSE::HTTP_BAD_REQUEST
                                        );
    }

    /**
     * Update Asset
     * @param $identifier Asset
     * @return jsonResponse Updated Asset
     */
    public function updateAssetAction($identifier, Request $request)
    {
        $data = $this->getDecodedContent($request->getContent());
        $result = [];
        if ($identifier) {
            $asset = $this->container->get('webkul_dam.repository.asset')->findOneByCode($identifier);

            if ($asset) {
                $connectorService = $this->get('dam.connector.service');
                if (isset($data['media'])) {
                    foreach ($data['media'] as $mediaKey => $media) {
                        $filePath = $connectorService->changeUrlToContent($media, $data['code'], $mediaKey);
                        if ($filePath) {
                            $data['media'][$mediaKey] = $filePath;
                        }
                    }
                }
        
                if (isset($data['tags'])) {
                    $data['tags'] = implode(' & ', $data['tags']);
                }
        
                if (isset($data['categories'])) {
                    $data['categories'] = implode(' & ', $data['categories']);
                }
        
                // $fst->put($filePath, $data);
                $updater = $this->get('webkul_dam.updater.asset');
                $saver = $this->get('webkul_dam.saver.asset');
                
                $updater = $updater->update($asset, $data);
                $saver = $saver->save($asset);
                $result = $this->objectToIndex($asset);
            } else {
                $result['error'] = "Asset with this code is not exist !!";
            }
        } else {
            $result['error'] = "Some error occured!! Code is not defined.";
        }

        return !isset($result['error']) ? new JsonResponse($result)
                                        : new JsonResponse(
                                            $result,
                                            RESPONSE::HTTP_BAD_REQUEST
                                        );
    }

    /**
     * Create your object to index array
     */
    protected function objectToIndex($repo)
    {
        $router = $this->get('router');

        $medias = [];
        foreach ($repo->getMedias() as $media) {
            $url = $router->generate('webkuldam_media_download', [
                                                    'identifier' => rawurlencode($media->getFilePath())
                                                ], UrlGeneratorInterface::ABSOLUTE_URL);
            $medias[] = $url;
        }

        $tags = [];
        foreach ($repo->getTags() as $tag) {
            $tags[] = $tag->getCode();
        }

        $categories = [];
        foreach ($repo->getCategory() as $category) {
            $categories[] = $category->getCode();
        }

        $asset = [];
        $asset['id'] = $repo->getId();
        $asset['code'] = $repo->getCode();
        $asset['description'] = $repo->getDescription();
        $asset['favorite'] = $repo->getStarred();
        $asset['title'] = $repo->getTitle();
        $asset['tags'] = $tags;
        $asset['categories'] = $categories;
        $asset['medias'] = $medias;
        $asset['expirationData'] = $repo->getExpirationDate();
        $asset['createdAt'] = $repo->getCreatedAt();
        $asset['updateAt'] = $repo->getUpdatedAt();

        return $asset;
    }

    /**
     * Get the JSON decoded content. If the content is not a valid JSON, it throws an error 400.
     *
     * @param string $content content of a request to decode
     *
     * @throws BadRequestHttpException
     *
     * @return array
     */
    protected function getDecodedContent($content)
    {
        $decodedContent = json_decode($content, true);

        if (null === $decodedContent) {
            throw new BadRequestHttpException('Invalid json message received');
        }

        return $decodedContent;
    }

    /**
     * Create asset categories
     * @param Request $request
     * @return JsonResponse
     */
    public function createAssetCategoryAction(Request $request)
    {
        $result = [];
        $data = $this->getDecodedContent($request->getContent());
        if (isset($data['code'])) {
            if (!($this->findCategory($data['code']))) {
                $factory = $this->get('webkul_dam.factory.category');
                $saver = $this->get('webkul_dam.saver.category');
                $em = $this->getDoctrine()->getManager();
                $parent = isset($data['parent']) ? $data['parent'] : null;
                $labels = isset($data['label']) && !empty($data['label']) ? $data['label'] : null;
                $category = $factory->create();
        
                if ($parent) {
                    $parent = $this->findCategory($parent);

                    if ($parent) {
                        $category->setParent($parent);
                    } else {
                        return new JsonResponse(
                            ["error" => "some error occured!! defined parent does not exists"],
                            RESPONSE::HTTP_BAD_REQUEST
                        );
                    }
                }
        
                $category->setCode($data['code']);
                
                $saver->save($category);
                
                if ($labels) {
                    foreach ($labels as $locale => $label) {
                        $categoryTranslation = new AssetCategoryTranslation();
                        $categoryTranslation->setLabel($label);
                        $categoryTranslation->setLocale($locale);
                        $categoryTranslation->setForeignKey($category);
                        $em->persist($categoryTranslation);
                    }
                }
                
                $em->flush();
                $result['id'] = $category->getId();
                $result['code'] = $category->getCode();
                $result['parent'] = isset($data['parent']) ? $data['parent'] : null;
                $result['labels'] = $labels;
            } else {
                $result['error'] = "some error occured!! Category code is already exist";
            }
        } else {
            $result['error'] = "some error occured!! Category code is not defined";
        }
 

        return !isset($result['error']) ? new JsonResponse($result)
                                        : new JsonResponse(
                                            $result,
                                            RESPONSE::HTTP_BAD_REQUEST
                                        );
    }

    /**
    * Update asset categories
    * @param Request $request
    * @param $identifier
    * @return JsonResponse
    */
    public function updateAssetCategoryAction(Request $request, $identifier)
    {
        $result = [];
        $data = $this->getDecodedContent($request->getContent());
        if (isset($identifier)) {
            if ($category = $this->findCategory($identifier)) {
                $saver = $this->get('webkul_dam.saver.category');
                $em = $this->getDoctrine()->getManager();
                $parent = isset($data['parent']) ? $data['parent'] : null;
                $labels = isset($data['label']) && !empty($data['label']) ? $data['label'] : null;
        
                if ($parent) {
                    $parent = $this->findCategory($parent);

                    if ($parent) {
                        $category->setParent($parent);
                    } else {
                        return new JsonResponse(
                            ["error" => "some error occured!! defined parent does not exists"],
                            RESPONSE::HTTP_BAD_REQUEST
                        );
                    }
                }

                $saver->save($category);

                if ($labels) {
                    foreach ($labels as $locale => $label) {
                        $categoryTranslation = $category->getTranslation($locale);
                        
                        if (!($categoryTranslation->getLabel())) {
                            $categoryTranslation = new AssetCategoryTranslation();
                        }
                        $categoryTranslation->setLabel($label);
                        $categoryTranslation->setLocale($locale);
                        $categoryTranslation->setForeignKey($category);
                        $em->persist($categoryTranslation);
                    }
                }
                $em->flush();
                
                $result['id'] = $category->getId();
                $result['code'] = $category->getCode();
                $result['parent'] = isset($data['parent']) ? $data['parent'] : null;
                $result['labels'] = $labels;
            } else {
                $result['error'] = "some error occured!! Category code is not exist";
            }
        } else {
            $result['error'] = "some error occured!! identifier is not defined";
        }

        return !isset($result['error']) ? new JsonResponse($result)
                                        : new JsonResponse(
                                            $result,
                                            RESPONSE::HTTP_BAD_REQUEST
                                        );
    }

    /**
     * get asset categories
     * @param Request $request
     * @return JsonResponse
     */
    public function getAllCategoriesAction(Request $request)
    {
        $page = $request->query->get('page');
        $limit = $request->query->get('limit');
        $currentPage = isset($page) ? $page : 1;
        $currentLimit = isset($limit) ? $limit : 10;

        $categoryQuery = $this->get('webkul_dam.repository.category')
                           ->createQueryBuilder('c')
                           ->orderBy('c.root', 'ASC')
                           ->getQuery();

        $paginator = $this->paginate($categoryQuery, $currentPage, $currentLimit);

        $category = $paginator->getIterator()->getArrayCopy();
        
        $categories = [];

        foreach ($category as $cat) {
            $translations = [];
            foreach ($cat->getTranslations() as $translation) {
                $translations[$translation->getLocale()] = $translation->getLabel();
            }

            $parent = $cat->getParent() ? $cat->getParent()->getCode() : null;
            $categories[] = [
                            "id" => $cat->getId(),
                            "code" => $cat->getCode(),
                            "parent" => $parent,
                            "label" => $translations
                        ];
        }

        return new JsonResponse($categories);
    }

    /**
     * Find a category from its id
     *
     * @param int $categoryId
     *
     * @throws NotFoundHttpException
     *
     * @return CategoryInterface
     */
    protected function findCategory($parent)
    {
        $categoryRepository = $this->get('webkul_dam.repository.category');
        $category = $categoryRepository->findOneByIdentifier($parent);
        return $category;
    }

    /**
     * @param Request $request
     *
     * @throws BadRequestHttpException
     *
     * @return Response
     *
     * @AclAncestor("webkul_dam_configuration")
     */
    public function deleteAction($code)
    {
        $result = [];
        $em = $this->getDoctrine()->getManager();
        $asset = $this->get('webkul_dam.repository.asset')->findOneByCode($code);

        if ($asset) {
            foreach ($asset->getMedias() as $media) {
                $em->remove($media);
            }
            $em->remove($asset);
            $em->flush();
            $result['success'] = sprintf("the asset %s is successfully deleted", $code);
        } else {
            $result['error'] = sprintf("there is some error while deleting asset code %s, Either asset not exit or already deleted", $code);
        }

        return !isset($result['error']) ? new JsonResponse($result)
                                        : new JsonResponse(
                                            $result,
                                            RESPONSE::HTTP_BAD_REQUEST
                                        );
    }
}
