<?php
/**
 * Holds the news post object.
 * @package Sakura
 */

namespace Sakura\News;

use Carbon\Carbon;
use Sakura\Comment;
use Sakura\DB;
use Sakura\User;

/**
 * News post object.
 * @package Sakura
 * @author Julian van de Groep <me@flash.moe>
 */
class Post
{
    /**
     * The format the comment categories should follow.
     */
    private const COMMENT_CATEGORY_FORMAT = "news-%s-%u";

    /**
     * The id of this news post.
     * @var int
     */
    public $id = 0;

    /**
     * The category this post is part of.
     * @var Category
     */
    public $category = null;

    /**
     * The user who made this post.
     * @var User
     */
    public $user = null;

    /**
     * The title of this news post.
     * @var string
     */
    public $title = "";

    /**
     * The content of this news post.
     * @var string
     */
    public $text = "";

    /**
     * When the post was created.
     * @var Carbon
     */
    public $created = null;

    /**
     * When the post was last updated.
     * @var Carbon
     */
    public $updated = null;

    /**
     * When the post was deleted.
     * @var Carbon
     */
    public $deleted = null;

    /**
     * A cache of the amount of comments this post has.
     * @var int
     */
    private $commentCountCache = 0;

    /**
     * A cache of comments.
     * @var array
     */
    private $commentsCache = [];

    /**
     * Constructor.
     * @param int $id
     */
    public function __construct(int $id = 0)
    {
        if ($id === 0) {
            return;
        }

        $data = DB::table('news_posts')
            ->where('post_id', $id)
            ->first();

        if ($data) {
            $this->id = intval($data->post_id);
            $this->category = new Category(intval($data->category_id));
            $this->user = User::construct(intval($data->user_id));
            $this->title = $data->post_title;
            $this->text = $data->post_text;
            $this->created = new Carbon($data->created_at);
            $this->updated = new Carbon($data->updated_at);
            $this->deleted = new Carbon($data->deleted_at);
        }
    }

    public static function fromRow($data)
    {
        $cat = new Post;

        $cat->id = intval($data->post_id);
        $cat->category = new Category(intval($data->category_id));
        $cat->user = User::construct(intval($data->user_id));
        $cat->title = $data->post_title;
        $cat->text = $data->post_text;
        $cat->created = new Carbon($data->created_at);
        $cat->updated = new Carbon($data->updated_at);
        $cat->deleted = new Carbon($data->deleted_at);

        return $cat;
    }

    /**
     * Saving changes to this news post.
     */
    public function save(): void
    {
        $data = [
            'category_id' => $this->category->id,
            'user_id' => $this->user->id,
            'post_title' => $this->title,
            'post_text' => $this->text,
        ];

        // Update if id isn't 0
        if ($this->id) {
            $data['updated_at'] = Carbon::now();

            DB::table('news_posts')
                ->where('post_id', $this->id)
                ->update($data);
        } else {
            $this->id = DB::table('news_posts')
                ->insertGetId($data);
        }
    }

    /**
     * Deleting this news post.
     */
    public function delete(): void
    {
        DB::table('news_posts')
            ->where('post_id', $this->id)
            ->update(['deleted_at' => Carbon::now()]);
    }

    /**
     * Count the amount of comments this post has.
     * @return int
     */
    public function commentCount(): int
    {
        if (!$this->commentCountCache) {
            $this->commentCountCache = DB::table('comments')
                ->where('comment_category', sprintf(self::COMMENT_CATEGORY_FORMAT, $this->category->id, $this->id))
                ->count();
        }

        return $this->commentCountCache;
    }

    /**
     * Get the comments on this post.
     * @return array
     */
    public function comments(): array
    {
        if (!$this->commentsCache) {
            $commentIds = DB::table('comments')
                ->where('comment_category', sprintf(self::COMMENT_CATEGORY_FORMAT, $this->category->id, $this->id))
                ->orderBy('comment_id', 'desc')
                ->where('comment_reply_to', 0)
                ->get(['comment_id']);
            $commentIds = array_column($commentIds, 'comment_id');

            foreach ($commentIds as $comment) {
                $this->commentsCache[$comment] = new Comment($comment);
            }
        }

        return $this->commentsCache;
    }
}