<?php

namespace App\Http\Controllers\Gallery;

use App\Facade\Theme;
use App\Helpers\DbHelper;
use App\Http\Controllers\Controller;
use App\Label;
use App\Photo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class StatisticsController extends Controller
{
    public function albumSizeByPhotosChart(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $stats = DB::table('photos')
            ->whereIn('photos.album_id', DbHelper::getAlbumIDsForCurrentUser())
            ->join('albums', 'albums.id', '=', 'photos.album_id')
            ->groupBy('albums.name')
            ->select('albums.name', DB::raw('count(photos.id) as photo_count'))
            ->orderBy('photo_count', 'desc')
            ->limit(10)
            ->get();

        $labels = [];
        $data = [];

        foreach ($stats as $stat)
        {
            $labels[] = $stat->name;
            $data[] = $stat->photo_count;
        }

        return response()->json([
            'labels' => $labels,
            'backgrounds' => $this->rotateColoursForData($data),
            'data' => $data
        ]);
    }

    public function albumSizeByPhotoSizeChart(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $stats = DB::table('photos')
            ->whereIn('photos.album_id', DbHelper::getAlbumIDsForCurrentUser())
            ->join('albums', 'albums.id', '=', 'photos.album_id')
            ->groupBy('albums.name')
            ->select('albums.name', DB::raw('sum(photos.file_size) as photo_size'))
            ->orderBy('photo_size', 'desc')
            ->limit(10)
            ->get();

        $labels = [];
        $data = [];

        foreach ($stats as $stat)
        {
            $labels[] = $stat->name;
            $data[] = ceil($stat->photo_size / 1024 / 1024);
        }

        return response()->json([
            'labels' => $labels,
            'backgrounds' => $this->rotateColoursForData($data),
            'data' => $data
        ]);
    }

    public function camerasChart(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $stats = DB::table('photos')
            ->where([
                ['camera_make', '!=', ''],
                ['camera_model', '!=', '']
            ])
            ->whereIn('album_id', DbHelper::getAlbumIDsForCurrentUser())
            ->groupBy('camera_make', 'camera_model')
            ->select('camera_make', 'camera_model', DB::raw('count(*) as photo_count'))
            ->orderBy('photo_count', 'desc')
            ->get();

        $labels = [];
        $data = [];

        foreach ($stats as $stat)
        {
            // Remove the model from the make if it starts with it
            // E.g. CANON - CANON EOS 1200D becomes just CANON EOS 1200D
            if (substr($stat->camera_model, 0, strlen($stat->camera_make)) == $stat->camera_make)
            {
                $stat->camera_make = trim(substr($stat->camera_make, strlen($stat->camera_make)));
            }

            $labels[] = sprintf('%s %s', $stat->camera_make, $stat->camera_model);
            $data[] = $stat->photo_count;
        }

        return response()->json([
            'labels' => $labels,
            'backgrounds' => $this->rotateColoursForData($data),
            'data' => $data
        ]);
    }

    public function fileSizeChart(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $labels = [
            trans('gallery.statistics.file_sizes_legend.small'),
            trans('gallery.statistics.file_sizes_legend.medium'),
            trans('gallery.statistics.file_sizes_legend.large'),
            trans('gallery.statistics.file_sizes_legend.huge')
        ];
        $data = [0, 0, 0, 0];

        $stats = DB::table('photos')->whereIn('album_id', DbHelper::getAlbumIDsForCurrentUser())->orderBy('id');
        $stats->chunk(100, function($photos) use (&$data)
        {
            foreach ($photos as $photo)
            {
                if ($photo->file_size < (1 * 1024 * 1024))
                {
                    $data[0]++;
                }
                else if ($photo->file_size < (3 * 1024 * 1024))
                {
                    $data[1]++;
                }
                else if ($photo->file_size < (5 * 1024 * 1024))
                {
                    $data[2]++;
                }
                else if ($photo->file_size >= (5 * 1024 * 1024))
                {
                    $data[3]++;
                }
            }
        });

        return response()->json([
            'labels' => $labels,
            'backgrounds' => $this->rotateColoursForData($data),
            'data' => $data
        ]);
    }

    public function index(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        // Numbers for at-a-glance
        $albumIDs = DbHelper::getAlbumIDsForCurrentUser();

        $albumCount = count($albumIDs);
        $labelCount = Label::all()->count();
        $photoCount = Photo::whereIn('album_id', $albumIDs)->count();

        return Theme::render('gallery.statistics', [
            'album_count' => $albumCount,
            'label_count' => $labelCount,
            'photo_count' => $photoCount
        ]);
    }

    public function photosCombined(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $labels = [];
        $data = [
            ['label' => trans('gallery.statistics.photos_combined.taken'), 'values' => []],
            ['label' => trans('gallery.statistics.photos_combined.uploaded'), 'values' => []]
        ];

        foreach ($this->lastXMonthsDates(18) as $date)
        {
            $fromDate = sprintf('%04d-%02d-01 00:00:00', $date[0], $date[1]);
            $toDate = sprintf('%04d-%02d-%02d 23:59:59', $date[0], $date[1], cal_days_in_month(CAL_GREGORIAN, $date[1], $date[0]));

            $photoCountTaken = Photo::whereBetween('taken_at', array($fromDate, $toDate))->count();
            $photoCountUploaded = Photo::whereBetween('created_at', array($fromDate, $toDate))->count();

            $labels[] = date('M Y', strtotime($fromDate));
            $data[0]['values'][] = $photoCountTaken;
            $data[1]['values'][] = $photoCountUploaded;
        }

        $data[0]['values'] = array_reverse($data[0]['values']);
        $data[1]['values'] = array_reverse($data[1]['values']);

        return response()->json([
            'labels' => array_reverse($labels),
            'data' => $data
        ]);
    }

    public function photosTaken12Months(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $labels = [];
        $data = [];

        foreach ($this->lastXMonthsDates() as $date)
        {
            $fromDate = sprintf('%04d-%02d-01 00:00:00', $date[0], $date[1]);
            $toDate = sprintf('%04d-%02d-%02d 23:59:59', $date[0], $date[1], cal_days_in_month(CAL_GREGORIAN, $date[1], $date[0]));

            $photoCount = Photo::whereBetween('taken_at', array($fromDate, $toDate))->count();

            $labels[] = date('M Y', strtotime($fromDate));
            $data[] = $photoCount;
        }

        return response()->json([
            'labels' => array_reverse($labels),
            'data' => array_reverse($data)
        ]);
    }

    public function photosUploaded12Months(Request $request)
    {
        $this->authorizeForUser($this->getUser(), 'statistics.public-access');

        $labels = [];
        $data = [];

        foreach ($this->lastXMonthsDates() as $date)
        {
            $fromDate = sprintf('%04d-%02d-01 00:00:00', $date[0], $date[1]);
            $toDate = sprintf('%04d-%02d-%02d 23:59:59', $date[0], $date[1], cal_days_in_month(CAL_GREGORIAN, $date[1], $date[0]));

            $photoCount = Photo::whereBetween('created_at', array($fromDate, $toDate))->count();

            $labels[] = date('M Y', strtotime($fromDate));
            $data[] = $photoCount;
        }

        return response()->json([
            'labels' => array_reverse($labels),
            'data' => array_reverse($data)
        ]);
    }

    private function lastXMonthsDates($x = 12)
    {
        $year = intval(date('Y'));
        $month = intval(date('m'));

        $datesNeeded = [];

        while (count($datesNeeded) < $x)
        {
            $datesNeeded[] = [$year, $month];

            $month--;
            if ($month == 0)
            {
                $month = 12;
                $year--;
            }
        }

        return $datesNeeded;
    }

    private function rotateColoursForData(array $data = [])
    {
        $colours = [
            '#d54d36',
            '#59c669',
            '#aa5ccf',
            '#85b83a',
            '#5f6cd9',
            '#bbb248',
            '#ca49a1',
            '#479341',
            '#d94b70',
            '#52b395',
            '#7b589e',
            '#da8f32',
            '#6e8bd0',
            '#8a722c',
            '#46aed7',
            '#aa5839',
            '#d48cca',
            '#64803f',
            '#a5506d',
            '#e19774'
        ];
        $result = [];
        $lastIndex = 0;

        for ($i = 0; $i < count($data); $i++)
        {
            $result[] = $colours[$lastIndex];
            $lastIndex++;
            if ($lastIndex >= count($colours))
            {
                $lastIndex = 0;
            }
        }

        return $result;
    }
}