<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Libs\Facades\Localization;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use MediaItem;
use Throwable;

class MediaManagerController extends Controller
{

    public function getList()
    {
        $page = request()->input("current");
        $sort = request()->input("sort");
        $search = request()->input("searchPhrase");
        $website = Localization::getWebsite();

        Paginator::currentPageResolver(function () use ($page) {
            return $page;
        });

        if (!empty($search)) {
            $query = MediaItem::where(function ($query) use ($search) {
                $query->orWhere('filename', 'like', "%{$search}%");
            });
        } else {
            $query = MediaItem::query();
        }
        if (empty($sort)) {
            $rows = $query->paginate(request()->input("rowCount"));
        } else {
            foreach ($sort as $field => $direction) {
                if (empty($direction) || !Str::is(strtolower($direction), "desc")) {
                    $order_direction = "asc";
                }
                $rows = $query->orderBy($field, strtolower($direction))->paginate(request()->input("rowCount"));
                break;
            }
        }

        $result = array(
            "total" => $rows->total(),
            "current" => $rows->currentPage(),
            "rowCount" => request()->input("rowCount"),
            "rows" => $rows->getCollection()
        );

        return response()->json($result);
    }

    public function getMedia($mediaId)
    {
        if (!is_numeric($mediaId)) {
            abort(400);
        }
        $mediaItem = MediaItem::find($mediaId);
        if (!$mediaItem) {
            return response()->json(null);
        }
        return response()->json($mediaItem);
    }

    public function postMedia($mediaId)
    {
        if (!is_numeric($mediaId)) {
            abort(400);
        }

        $data = array(
            'title' => request()->input('title', null, true),
            'alt' => request()->input('alt', null, true)
        );

        $validator = Validator::make(
            $data,
            array(
                'title' => 'required|max:150',
                'alt' => 'max:150'
            )
        );

        if ($validator->fails()) {
            $result = array(
                'success' => false,
                'error' => 'validation',
                'validation' => $validator->messages()->toArray()
            );
            return response()->json($result);
        }

        $mediaItem = MediaItem::find($mediaId);
        if (!$mediaItem) {
            $result = array(
                'success' => false,
                'error' => 'not found'
            );
            return response()->json(false);
        }

        $mediaItem->title = htmlspecialchars($data['title'], ENT_QUOTES, 'UTF-8');
        $mediaItem->alt = htmlspecialchars($data['alt'], ENT_QUOTES, 'UTF-8');

        $mediaItem->save();

        $result = array(
            'success' => true,
            'mediaItem' => $mediaItem
        );
        return response()->json($mediaItem);
    }

    public function getMore()
    {
        $validator = Validator::make(
            request()->all(),
            array(
                'lastId' => 'integer',
                'typeFilter' => 'array',
                'relatedFilter' => 'alpha_dash',
                'websiteFilter' => 'integer',
                'searchString' => ''
            )
        );
        if ($validator->fails()) {
            return response()->json(array('rows' => array()));
        }

        $lastId = request()->input("lastId");
        $typeFilter = request()->input("typeFilter");
        $relatedFilter = request()->input("relatedFilter");
        $websiteFilter = request()->input("websiteFilter");
        $searchString = request()->input("searchString");

        $website = Localization::getWebsite();

        $query = MediaItem::query();

        if (!empty($typeFilter)) {
            $realFilter = array_intersect($typeFilter, array("image", "video", "document"));
        } else {
            $realFilter = array("none");
        }
        $query->whereIn('media_type', $realFilter);

        if (!empty($relatedFilter)) {
            $query->where('related_type', $relatedFilter);
        }

        if (!empty($websiteFilter)) {
            $query->where('website_id', $websiteFilter);
        }

        if ($searchString && strlen(trim($searchString)) > 2) {
            $query->where(function ($q) use ($searchString) {
                $q->where('original_filename', 'like', '%'.$searchString.'%')
                    ->orWhere('title', 'like', '%'.$searchString.'%')
                    ->orWhere('filename', 'like', '%'.$searchString.'%');
            });
        }

        if ($lastId && is_numeric($lastId)) {
            $query->where('id', '<', $lastId);
        }

        $rows = $query->orderBy('id', 'desc')->take(request()->input("rowCount"));

        $result = array(
            "rowCount" => request()->input("rowCount"),
            "rows" => $rows->get()
        );

        return response()->json($result);
    }

    public function postUpload($uploadType = 'media_manager')
    {
        $website = Localization::getWebsite();
        $user = Auth::guard('admin')->user();

        if (!$user->hasPermission('backend.media.create')) {
            abort(403);
        }
        $file = request()->file('file');

        $relatedType = request()->input('relatedContentType');

        $destinationPath = config('path.internal.media');

        $originalFilename = $file->getClientOriginalName();

        $extension = $file->getClientOriginalExtension();
        $withoutExt = preg_replace('/\\.[^.\\s]{3,4}$/', '', $originalFilename);

        $mediaType = $this->getMediaType($extension);
        if (!$mediaType) {
            return response()->json('error', 403);
        }

        $newFilename = urlize($withoutExt);
        $finalName = $newFilename.'.'.$extension;
        //Checks for colliding filenames
        $i = 1;

        while (Storage::has($destinationPath.'/'.$finalName)) {
            $finalName = $newFilename.'-'.$i.'.'.$extension;
            $i++;
            //for safety
            if ($i > 100) {
                return response()->json('error', 400);
            }
        }

        $upload_success = request()->file('file')->move(Storage::path($destinationPath), $finalName);

        if ($upload_success) {
            $mediaItem = new MediaItem(array(
                'filename' => $finalName,
                'original_filename' => $originalFilename,
                'title' => $originalFilename,
                'extension' => $extension,
                'website_id' => $website->id,
                'related_type' => $relatedType,
                'media_type' => $mediaType,
                'backend_user_id' => $user->id
            ));

            if ($mediaType == MediaItem::MEDIA_TYPE_IMAGE) {
                //Generates internal thumbnail
                $img = Image::make(Storage::path($destinationPath.'/'.$finalName))->orientate();
                $mediaItem->width = $img->width();
                $mediaItem->height = $img->height();
                $img->fit(200, 200);
                $img->save(Storage::path(config('path.internal.thumbs').'/'.getFileNameSize($finalName, '200x200')));
            }

            $mediaItem->save();

            if ($uploadType == 'editor') {
                $editorImage = array(
                    'filelink' => Storage::url(config('path.internal.media') . '/'.$mediaItem->filename)
                );
                return response()->json($editorImage, 200);
            } else {
                return response()->json($mediaItem, 200);
            }
        } else {
            return response()->json('error', 400);
        }
    }

    public function postDelete($itemId)
    {
        $user = Auth::guard('admin')->user();

        if (!$user->hasPermission('backend.media.create')) {
            return response()->json(false);
        }

        $item = MediaItem::find($itemId);

        if (!$item) {
            return response()->json(false);
        }

        // Deletes main file
        $filename = $item->filename;
        $mediaPath = config('path.internal.media');
        if (Storage::has($mediaPath.'/'.$filename)) {
            Storage::delete($mediaPath.'/'.$filename);
        }

        // Deletes thumbs (for images)
        if ($item->media_type == MediaItem::MEDIA_TYPE_IMAGE) {
            $thumbsPath = config('path.internal.thumbs');
            $withoutExt = preg_replace('/\\.[^.\\s]{3,4}$/', '', $filename);
            $ext = pathinfo($mediaPath.'/'.$filename, PATHINFO_EXTENSION);

            foreach (glob($thumbsPath."/".$withoutExt."_*.".$ext) as $thumb) {
                Storage::delete($thumb);
            }
        }

        MediaItem::destroy($itemId);
        return response()->json(true);
    }

    public function getUpdateImageSizes()
    {
        $images = MediaItem::where('media_type', 'image')->get();
        $mediaPath = config('path.internal.media');
        foreach ($images as $image) {
            try {
                $img = Image::make(Storage::path($mediaPath.'/'.$image->filename));
                echo $image->filename.': '.$img->width().' x '.$img->height().'<br>';
                $image->width = $img->width();
                $image->height = $img->height();
                //$image->title = $image->original_filename;
                $image->save();
                $img->destroy();
            } catch (Throwable $e) {
                echo 'ERROR WITH IMAGE: '.$image->id.' - '.$image->filename.'<br>';
            }
        }
    }

    private function getMediaType($ext)
    {
        $allowedExts = config('backoffice.media.allowedExts');
        foreach ($allowedExts as $type => $allowedExt) {
            if (in_array($ext, $allowedExt)) {
                return $type;
            }
        }
        return false;
    }
}
