<?php

namespace App\Http\Controllers;

use App\Category;
use App\Comment;
use App\CommentDetail;
use App\Http\Resources\CommentResource;
use App\Http\Resources\TopicResource;
use App\Keyword;
use App\Rank;
use App\Topic;
use Carbon\Carbon;
use http\Env\Response;
use Illuminate\Http\Request;
use Validator;

class TopicController extends Controller
{
    const ITEM_PER_PAGE = 500;

    public function index()
    {
        $rank = Rank::orderBy('created_date', 'DESC')->first();
        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('rank_id', $rank->id)
            ->orderBy('created_at', 'DESC')
            ->orderBy('total_comment', 'DESC')
            ->get();

        return TopicResource::collection($list);
    }

    public function newTopic()
    {
        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->orderBy('created_at', 'DESC')
            /*->paginate(self::ITEM_PER_PAGE);*/
            ->paginate(50);

        return TopicResource::collection($list);
    }

    public function weeklyTopic()
    {
        $today = new Carbon();
        $today = $today->subDays(7);
        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('created_at', '>=', $today->format('Y-m-d') . ' 00:00:00')
            ->orderBy('created_at', 'DESC')
            ->paginate(100);

        return TopicResource::collection($list);
    }

    public function weeklyTopTopic()
    {
        $today = new Carbon();
        $today = $today->subDays(7);
        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('created_at', '>=', $today->format('Y-m-d') . ' 00:00:00')
            ->orderBy('total_comment', 'DESC')
            ->orderBy('created_at', 'DESC')
            ->paginate(5);

        return TopicResource::collection($list);
    }

    public function yesterdayTopTopic()
    {
        $latestRank = Rank::orderBy('created_date', 'DESC')->first();
        if (!isset($latestRank)) return response()->json(['status' => 'error', 'message' => 'Rank is no valid.'], 403);

        $lastRank = Rank::where('id', '<', $latestRank->id)
            ->orderBy('id', 'DESC')
            ->first();

        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('rank_id', $lastRank->id)
            ->orderBy('total_comment', 'DESC')
            ->orderBy('created_at', 'DESC')
            ->paginate(5);

        return TopicResource::collection($list);
    }

    public function keywordTopic($keyword = '')
    {
        $keywordId = '';
        if ($keyword != "") {
            $keywordItem = Keyword::where('name', $keyword)->first();
            $keywordId = (isset($keywordItem)) ? $keywordItem->id : '';
        }

        $list = Topic::select('topics.id', 'topics.code', 'topics.title', 'topics.thumbnail', 'topics.total_comment', 'topics.created_at')
            ->join('topic_keywords', 'topics.id', '=', 'topic_keywords.topic_id')
            ->where('topic_keywords.keyword_id', $keywordId)
            ->published()
            ->orderBy('topics.total_comment', 'DESC')
            ->orderBy('topics.created_at', 'DESC')
            ->paginate(50);

        return TopicResource::collection($list);
    }

    public function categoryTopic($slug = '')
    {
        $category = Category::published()->where('slug', $slug)->first();
        $categoryId = isset($category) ? $category->id : '';

        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('category_id', $categoryId)
            ->orderBy('total_comment', 'DESC')
            ->orderBy('created_at', 'DESC')
            ->paginate(50);

        return TopicResource::collection($list);
    }

    public function searchTopic(Request $request)
    {
        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')->published();

        if ($request->has('q') && $request->get('q') !== "") {
            $keyword = $request->get('q');
            $list = $list->where('title', 'like', "%$keyword%");
        }

        $list = $list->orderBy('total_comment', 'DESC')
            ->orderBy('created_at', 'DESC')
            ->paginate(100)
            ->appends(request()->query());

        return TopicResource::collection($list);
    }

    public function rankTopic($code = 1)
    {
        $latestRank = Rank::orderBy('created_date', 'DESC')->first();
        $rank = null;
        if ($code > 1) {
            $currentRankNumber = $latestRank->rank_number - ($code - 1);
            $rank = Rank::where('rank_number', $currentRankNumber)->first();
        } else {
            $rank = $latestRank;
        }

        $list = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('rank_id', $rank->id)
            ->orderBy('total_comment', 'DESC')
            ->orderBy('created_at', 'DESC')
            ->paginate(50);

        return TopicResource::collection($list);
    }

    public function checkRank()
    {
        $latestRank = Rank::orderBy('created_date', 'DESC')->first();
        $prevRank = Rank::where('created_date', '<', $latestRank->created_date)->orderBy('created_date', 'DESC')->first();

        return response()->json([
            'current'  => $latestRank->created_date,
            'has_next' => false,
            'has_prev' => isset($prevRank) ? true : false,
        ], 200);
    }

    public function checkNextRank($code = 2)
    {
        if ($code < 1) return response()->json(['status' => 'error', 'message' => 'Rank is not valid.'], 403);

        $latestRank = Rank::orderBy('created_date', 'DESC')->first();
        if (!isset($latestRank)) return response()->json(['status' => 'error', 'message' => 'Rank is not valid.'], 403);

        $currentRankNumber = $latestRank->rank_number - ($code - 1);
        $currentRank = Rank::where('rank_number', $currentRankNumber)->first();
        if (!isset($currentRank)) return response()->json(['status' => 'error', 'message' => 'Rank is not valid.'], 403);

        $nextRank = Rank::where('rank_number', $currentRankNumber + 1)->count();
        $prevRank = Rank::where('rank_number', $currentRankNumber - 1)->count();

        return response()->json([
            'current'  => $currentRank->created_date,
            'has_next' => ($nextRank > 0) ? true : false,
            'has_prev' => ($prevRank > 0) ? true : false,
        ], 200);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
                'title'   => ['required'],
                'content' => ['required'],
                'urls'    => ['required'],
            ]
        );
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);

        $params = $request->all();
        $thumbnail = 'noimg@2x.png';
        if (isset($params['has_thumbnail']) && $params['has_thumbnail'] != false && $params['thumbnail'] != "") {
            $thumbnail = TopicResource::createThumb($params['thumbnail']);
        }

        $today = date('Y-m-d');
        $rank = Rank::where('created_date', $today)->first();
        if (!isset($rank)) {
            $checkMax = Rank::orderBy('rank_number', 'DESC')->first();
            $rank_number = isset($checkMax) ? $checkMax->rank_number : 0;
            $rank_number += 1;
            $rank = Rank::create([
                'created_date' => $today,
                'rank_number'  => $rank_number,
                'total_post'   => 1,
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s')
            ]);
        }

        $topic = Topic::create([
            'code'             => TopicResource::generateCode(),
            'title'            => $params['title'],
            'thumbnail'        => $thumbnail,
            'author'           => (!$params['is_anonymous']) ? $params['author'] : '',
            'rank_id'          => $rank->id,
            'is_allow_comment' => true,
            'is_activated'     => true, //false
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s')
        ]);

        $commentData = [
            'topic_id'         => $topic->id,
            /*'parent_id'        => 0,*/
            'content'          => $params['content'],
            'author'           => (!$params['is_anonymous']) ? $params['author'] : '',
            'is_anonymous'     => $params['is_anonymous'],
            'is_show_id'       => $params['is_show_id'],
            'is_allow_comment' => true,
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s')
        ];
        if ($thumbnail != 'noimg@2x.png') $commentData['image'] = $thumbnail;
        $comment = Comment::create($commentData);
        if ($params['is_show_id'] == true) {
            $comment->idx = $comment->id;
        } else {
            $comment->idx = 1;
        }
        $comment->save();

        foreach ($params['urls'] as $item) {
            $cmtData = [
                'comment_id' => $comment->id,
                'content'     => $item['text'],
                'current_img' => -1,
                'is_url'      => $item['is_url'],
                'created_at'       => date('Y-m-d H:i:s'),
                'updated_at'       => date('Y-m-d H:i:s')
            ];
            if ($item['is_url']) {
                $cmtData['title'] = $item['title'];
                $cmtData['domain'] = $item['domain'];
                $cmtData['description'] = $item['description'];
                $cmtData['current_img'] = $item['current_img'];
                $thumbnailItem = 'noimg@2x.png';
                if ($item['current_img'] > -1 && $item['thumbnail'] != "") {
                    $thumbnailItem = TopicResource::createThumb($item['thumbnail']);
                }
                $cmtData['thumbnail'] = $thumbnailItem;
            }
            CommentDetail::create($cmtData);
        }

        return new TopicResource($topic);
    }

    public function show($code = 0)
    {
        $topic = Topic::select('id', 'code', 'title', 'thumbnail', 'total_comment', 'created_at')
            ->published()
            ->where('code', $code)
            ->first();
        if (!isset($topic)) return response()->json(['status' => 'error', 'message' => 'Topic is not valid.'], 403);

        /*$comments = Comment::with('detail')->select('id', 'image', 'like', 'dislike', 'author', 'is_anonymous', 'is_show_id', 'is_allow_comment', 'created_at')
            ->published()
            ->where('topic_id', $topic->id)
            ->orderBy('id')
            ->paginate(50);*/

        return response()->json(['topic' => $topic]);
    }

    public function getUrlData(Request $request)
    {
        $url = $request->url;

        $domain = null;
        $title = null;
        $metaTags = [];
        $images = [];
        $metaList = ['og:image', 'og:image:secure_url', 'twitter:url', 'twitter:title', 'twitter:image', 'twitter:description', 'description'];

        if ($url != "") {
            $contents = $this->getUrlContents($url);
            $protocol = 'http://';
            if (strpos($url, "https://") !== false) $protocol = "https://";

            $domain = str_replace("https://", "", $url);
            $domain = str_replace("http://", "", $domain);
            $domainOrigin = str_replace("www.", "", $domain);
            if (strpos($domainOrigin, "/") !== false) {
                $domain = explode("/", $domainOrigin);
                $domain = (count($domain) > 0) ? $domain[0] : $domainOrigin;
            }

            if (isset($contents) && is_string($contents)) {
                preg_match('/<title>([^>]*)<\/title>/si', $contents, $match);
                if (isset($match) && is_array($match) && count($match) > 0) {
                    $title = strip_tags($match[1]);
                }

                preg_match_all('/<[\s]*meta[\s]*name="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);
                if (isset($match) && is_array($match) && count($match) == 3) {
                    $originals = $match[0];
                    $names = $match[1];
                    $values = $match[2];
                    if (count($originals) == count($names) && count($names) == count($values)) {
                        for ($i = 0, $limiti = count($names); $i < $limiti; $i++) {
                            if (in_array($names[$i], $metaList)) {
                                $metaKey = str_replace(":", "_", $names[$i]);
                                $metaTags[$metaKey] = $values[$i]; //htmlentities($originals[$i])
                            }
                        }
                    }
                }

                preg_match_all('/<[\s]*meta[\s]*property="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);
                if (isset($match) && is_array($match) && count($match) == 3) {
                    $originals = $match[0];
                    $names = $match[1];
                    $values = $match[2];
                    if (count($originals) == count($names) && count($names) == count($values)) {
                        for ($i = 0, $limiti = count($names); $i < $limiti; $i++) {
                            if (in_array($names[$i], $metaList)) {
                                $metaKey = str_replace(":", "_", $names[$i]);
                                $metaTags[$metaKey] = $values[$i]; //htmlentities($originals[$i])
                            }
                        }
                    }
                }

                if (isset($metaTags['og_image']) && $metaTags['og_image'] != "") {
                    $images[] = ['data_src' => $metaTags['og_image'], 'src_set' => '', 'src' => ''];
                }

                $htmlDom = new \DOMDocument();
                @$htmlDom->loadHTML($contents);
                $imageTags = $htmlDom->getElementsByTagName('img');
                foreach ($imageTags as $imageTag) {
                    $imgDataSrc = $imageTag->getAttribute('data-src');
                    $imgDataSrc = (strpos($imgDataSrc, "/") !== false && strpos($imgDataSrc, "/") == 0) ? $protocol . $domain . $imgDataSrc : $imgDataSrc;
                    $imgDataSrc = trim($imgDataSrc);
                    $imgSrcSet = $imageTag->getAttribute('srcset');
                    $imgSrcSet = (strpos($imgDataSrc, "/") !== false && strpos($imgSrcSet, "/") == 0) ? $protocol . $domain . $imgSrcSet : $imgSrcSet;
                    $imgSrcSet = trim($imgSrcSet);
                    $imgSrc = $imageTag->getAttribute('src');
                    $imgSrc = (strpos($imgDataSrc, "/") !== false && strpos($imgSrc, "/") == 0) ? $protocol . $domain . $imgSrc : $imgSrc;
                    $imgSrc = trim($imgSrc);

                    if ((!empty($imgDataSrc) && strpos($imgDataSrc, "http") !== false) ||
                        (!empty($imgSrcSet) && strpos($imgSrcSet, "http") !== false) ||
                        (!empty($imgSrc) && strpos($imgSrc, "http") !== false)) {
                        $images[] = array(
                            'data_src' => $imgDataSrc,
                            'src_set'  => $imgSrcSet,
                            'src'      => $imgSrc,
                        );
                    }
                }
                unset($imageTags);
                unset($htmlDom);
            }
        }

        return response()->json([
            'domain'   => $domain,
            'title'    => $title,
            'metaTags' => $metaTags,
            'images'   => $images,
        ], 200);
    }

    public function getUrlContents($url, $maximumRedirections = null, $currentRedirection = 0)
    {
        $result = false;
        $contents = @file_get_contents($url);
        if (isset($contents) && is_string($contents)) {
            preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $contents, $match);
            if (isset($match) && is_array($match) && count($match) == 2 && count($match[1]) == 1) {
                if (!isset($maximumRedirections) || $currentRedirection < $maximumRedirections) {
                    return $this->getUrlContents($match[1][0], $maximumRedirections, ++$currentRedirection);
                }
                $result = false;
            } else {
                $result = $contents;
            }
        }
        return $contents;
    }
}
