<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class NewsController extends Controller
{
    private $EXTERNAL_NEWS_API;

    private static $NEWS_CATEGORY = 1;
    private static $CALENDAR_CATEGORY = 42;
    private static $EXTERNAL_NEWS_CATEGORY = 44;
    private static $BLOG_CATEGORY = 45;

    private static $BASE_SQL = <<<QUERY
SELECT `news`.`id`, `content`.`title`, `content`.`content`, `news`.`podcast` AS `podcast_id`, `news`.`video`, `news`.`keywords`, `news`.`titlewithdate`, 
       `news`.`creationdt` AS `published`, `content`.`creator`, `news`.`pubupdatedt` AS `edited`,
       `news`.`startdt` AS `starts`, `news`.`enddt` AS `ends`, `content`.`extref` AS `external_id`,
       `content`.`showsource` AS `showsource`, `sources`.`title` AS `source`, `sources`.`url` AS `source_url`, 
       `themes`.`title` AS `theme`, `themes`.`thumbnail` AS `theme_thumbnail`, `themes`.`slug` AS `theme_slug`,
       `regions`.`title` AS `region`, `regions`.`slug` as `region_slug`
    FROM `news`    
        LEFT JOIN `news_target_content` AS `content` ON `content`.`news` = `news`.`id`
        LEFT JOIN `news_regions` AS `regions` ON  `regions`.`id` = `news`.`region`
        LEFT JOIN `news_sources` AS `sources` ON  `sources`.`id` = `news`.`source`
        LEFT JOIN `news_themes` AS `themes` ON  `themes`.`id` = `news`.`theme`
    WHERE (`news`.`category` = :category OR `news`.`category` = :secondarycategory) AND `content`.`target` = 1 AND `news`.`active` = 1 AND `content`.`active` = 1 AND `content`.`published` = 1
QUERY;

    private static $LOAD_IMAGES =
        'SELECT `id`, `file`, `description` AS `title` FROM `news_pictures` WHERE `news` = :newsId AND `active` = 1';
 
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->EXTERNAL_NEWS_API = env('EXTERNAL_NEWS_API', '//');
    }

    /**
    * Lijst van alle nieuwsberichten
    */
    public function newslist(Request $request, $filter = null) {
	$count = (int)$request->get('aantal', 15);
	$page = (int)$request->get('pagina', 1);
        if($count <= 0 || $page <= 0) {
          return abort(400);
        }
 
        $filterSql = "";
        $params = ['category' => self::$NEWS_CATEGORY, 'secondarycategory' => self::$EXTERNAL_NEWS_CATEGORY];
        if($filter) { 
            foreach($filter as $field => $value) {
                $paramName = preg_replace('/[^A-Za-z0-9]/', '', $field);
                $filterSql .= " AND $field = :$paramName";
                $params[$paramName] = $value;
            }
        }

        $start = ($page - 1) * $count;
        $newsItems = app('db')->select(self::$BASE_SQL
            . $filterSql
            . ' ORDER BY COALESCE(`news`.`pubupdatedt`, `news`.`creationdt`) DESC'
            . ' LIMIT ' . (int)$start . ', ' . (int)$count, $params);

        $result = array();
        foreach($newsItems as $newsItem) {
            // Note: content is stored in the database with an additional addslashes() - don't ask why, just remove it :)
            $newsItem->content = $newsItem->content;
            $pictures = app('db')->select(self::$LOAD_IMAGES, ['newsId' => $newsItem->id]);
            $result[] = new \Model\NewsItem($newsItem, $pictures);
        }

        return response()->json(['page' => $page, 'count' => $count, 'news' => $result]);
    }

    public function regionlist(Request $request, $region) {
        return $this->newslist($request, ['`regions`.`slug`' => $region]);
    } 

    public function themelist(Request $request, $theme) {
        return $this->newslist($request, ['`themes`.`slug`' => $theme]);
    }

    public function findnews(Request $request, $query) {
	$page = (int)$request->get('pagina', 1);
        if($page <= 0) {
          return abort(400);
        }
  
        $query = strip_tags(urldecode($query));
        $searchRange = [
            (new \DateTimeImmutable())->setDate(date('Y') + 1 - $page, 1, 1),
            (new \DateTimeImmutable())->setDate(date('Y') + 2 - $page, 1, 1)];
 
        $newsItems = app('db')->select(self::$BASE_SQL
            . ' AND `news`.`creationdt` >= :startRange AND `news`.`creationdt` <= :endRange'
            . ' AND MATCH(`content`.`title`, `content`.`content`) AGAINST(:query IN BOOLEAN MODE)'
            . ' ORDER BY COALESCE(`news`.`pubupdatedt`, `news`.`creationdt`) DESC'
            . ' LIMIT 0, 20', [
                'category' => self::$NEWS_CATEGORY,
                'secondarycategory' => self::$EXTERNAL_NEWS_CATEGORY,
                'startRange' => $searchRange[0]->format('Y-m-d'),
                'endRange' => $searchRange[1]->format('Y-m-d'),
                'query' => $query
            ]);

        $result = array();
        foreach($newsItems as $newsItem) {
            // Note: content is stored in the database with an additional addslashes() - don't ask why, just remove it :)
            $newsItem->content = $newsItem->content;
            $pictures = app('db')->select(self::$LOAD_IMAGES, ['newsId' => $newsItem->id]);
            $newsItem = new \Model\NewsItem($newsItem, $pictures);
            $newsItem->title = \Helpers::HighlightQuery($query, $newsItem->title);
            $newsItem->content = \Helpers::HighlightQuery($query, $newsItem->content);
            $result[] = $newsItem;
        }

        return response()->json(['page' => $page, 'count' => 0, 'news' => $result, 'query' => $query]);
    }

    /**
    * Agendaberichten ophalen
    */
    public function calendarlist(Request $request) {
      $today = new \DateTime('today');
      $agendaItems = app('db')->select(self::$BASE_SQL
          . ' AND `news`.`enddt` >= :today '
          . ' ORDER BY `news`.`startdt` ASC, `news`.`enddt` ASC', ['category' => self::$CALENDAR_CATEGORY, 'secondarycategory' => 0, 'today' => $today]);

        $result = array();
        foreach($agendaItems as $agendaItem) {
            // Note: content is stored in the database with an additional addslashes() - don't ask why, just remove it :)
            $agendaItem->content = $agendaItem->content;
            $pictures = app('db')->select(self::$LOAD_IMAGES, ['newsId' => $agendaItem->id]);
            $result[] = new \Model\CalendarEvent($agendaItem, $pictures);
        }

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

    /**
    * Blogitems ophalen
    */
    public function bloglist(Request $request, $from, $to) {
      $count = (int)$request->get('aantal', 15);
      $page = (int)$request->get('pagina', 1);
      if($count <= 0 || $page <= 0) {
        return abort(400);
      }

      $startIndex = ($page - 1) * $count;
      $start = new \DateTime($from);
      $end = new \DateTime($to);
      $blogItems = app('db')->select($sql = self::$BASE_SQL
          . ' AND `news`.`startdt` >= :start AND `news`.`startdt` <= :end '
          . ' ORDER BY `news`.`startdt` DESC'
          . ' LIMIT ' . (int)$startIndex . ', ' . (int)$count,
            ['category' => self::$BLOG_CATEGORY, 'secondarycategory' => 0, 'start' => $from, 'end' => $to]);

        $result = array();
        foreach($blogItems as $blogItem) {
            // Note: content is stored in the database with an additional addslashes() - don't ask why, just remove it :)
            $blogItem->content = $blogItem->content;
            $pictures = app('db')->select(self::$LOAD_IMAGES, ['newsId' => $blogItem->id]);
            if($blogItem->podcast_id > 0)
            {
              $podcast = app('db')->select(PodcastController::$BASE_SQL . ' AND `podcast`.`id` = :podcastId', ['podcastId' => $blogItem->podcast_id]);
              $podcast = count($podcast) ? $podcast[0] : null;
            }
            else
            {
              $podcast = null;
            }

            $result[] = new \Model\NewsItem($blogItem, $pictures, $podcast);
        }

        return response()->json(['page' => $page, 'count' => $count, 'items' => $result]);
    }


    /**
    * Populaire berichten ophalen
    */
    public function popularNews(Request $request) { 
        return $this->popularInCategory($request, self::$NEWS_CATEGORY, self::$EXTERNAL_NEWS_CATEGORY);
    }

    public function popularCalendar(Request $request) { 
        return $this->popularInCategory($request, self::$CALENDAR_CATEGORY);
    }

    protected function popularInCategory(Request $request, $category, $secondarycategory = -1) {
        $count = (int)$request->get('aantal', 5);
        $recent = app('db')->select(<<<QUERY
            SELECT `news`.`id`, COUNT(DISTINCT pagestats.visitor_ip) AS visitors 
            FROM news 
              INNER JOIN pagestats ON pagestats.type = :type AND pagestats.item_id = news.id 
              INNER JOIN `news_target_content` AS `content` ON `content`.`news` = `news`.`id`
            WHERE `news`.`startdt` >= DATE_SUB(CURRENT_TIMESTAMP, INTERVAL :interval DAY) 
              AND (`news`.`category` = :category OR `news`.`category` = :secondarycategory) AND `content`.`target` = 1 AND `news`.`active` = 1 AND `content`.`active` = 1
            GROUP BY news.id ORDER BY visitors DESC 
            LIMIT 0, :count
QUERY
        , [
          'type' => $category == self::$NEWS_CATEGORY ? 'nieuws'
                  : ( $category == self::$EXTERNAL_NEWS_CATEGORY ? 'nieuws'
                  : ($category == self::$CALENDAR_CATEGORY ? 'agenda'
                  : ( "" ) ) ),
          'interval' => $category == self::$NEWS_CATEGORY ? 30
                  : ($category == self::$EXTERNAL_NEWS_CATEGORY ? 30
                  : ($category == self::$CALENDAR_CATEGORY ? 0
                  : 30 ) ),
          'category' => $category,
          'secondarycategory' => $secondarycategory,
          'count' => $count
        ]);

        $result = array();
        foreach($recent as $item)
        {
            $newsItem = app('db')->select(self::$BASE_SQL . ' AND `news`.`id` = :newsId', ['category' => $category, 'secondarycategory' => $secondarycategory, 'newsId' => $item->id])[0];
            $pictures = app('db')->select(self::$LOAD_IMAGES, ['newsId' => $newsItem->id]);
            $result[] = new \Model\NewsItem($newsItem, $pictures);
        }

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

    /**
    * Specifiek nieuwsbericht ophalen
    */
    public function newsitem($id) {
      $item = $this->itemFromCategory(array(self::$NEWS_CATEGORY, self::$EXTERNAL_NEWS_CATEGORY), $id);
      if(!$item) {
        return abort(404);
      } 

      $data = array('version' => 1, 
	'news' => new \Model\NewsItem($item['data'], $item['images'], $item['podcast']));
      if($externalId = (int)$item['data']->external_id) {
        $externalSource = json_decode(file_get_contents($this->EXTERNAL_NEWS_API . 'news?source=api&externalid=' . (int)$externalId));
        if($externalSource) {
                $data['version'] = 2;
		$data['source'] = $externalSource->news;
        } 
      } 

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

    /**
    * Specifiek agendaitem ophalen
    */
    public function calendaritem($id) {
      $item = $this->itemFromCategory(self::$CALENDAR_CATEGORY, $id);
      return $item ? response()->json(new \Model\CalendarEvent($item['data'], $item['images'], $item['podcast'])) : abort(404);
    }

    private function itemFromCategory($category, $id) {
        $params = ['id' => (int)$id];
        if(is_array($category)) {
          $params['category'] = $category[0];
          $params['secondarycategory'] = $category[1];
        } else {
          $params['category'] = $category;
          $params['secondarycategory'] = 0;
        }
        $newsItem = app('db')->select(self::$BASE_SQL
            . ' AND `news`.`id` = :id LIMIT 0, 1', $params);
        
        if(count($newsItem) != 1) {
            return null;
        } else {
            // Note: content is stored in the database with an additional addslashes() - don't ask why, just remove it :)
            $newsItem[0]->content = $newsItem[0]->content;
            $images = app('db')->select(self::$LOAD_IMAGES, ['newsId' => $id]);
            $podcast = null;
            if($newsItem[0]->podcast_id > 0)
            {
              $podcast = app('db')->select(PodcastController::$BASE_SQL . ' AND `podcast`.`id` = :podcastId', ['podcastId' => $newsItem[0]->podcast_id]);
              $podcast = count($podcast) ? $podcast[0] : null;
            }

            return ['data' => $newsItem[0], 'images' => $images, 'podcast' => $podcast];
        }
    }
}
