<?php
/**
 * @package     Sven.Bluege
 * @subpackage  com_eventgallery
 *
 * @copyright   Copyright (C) 2005 - 2019 Sven Bluege All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */


namespace components\com_eventgallery\site\library\Data;

defined('_JEXEC') or die;

use lsolesen\pel\PelJpeg;
use lsolesen\pel\PelIfd;
use lsolesen\pel\Pel;
use lsolesen\pel\PelTag;

class Exif
{
    public $model = null;
    public $focallength = null;
    public $fstop = null;
    public $exposuretime = null;
    public $iso = null;
    public $creation_date = null;
    public $has90DegreeRotation = false;
    public $orientation = null;

    public function __construct($jsonStringData = null) {
        if (isset($jsonStringData)) {
            $data = json_decode($jsonStringData);
            if (json_last_error() == JSON_ERROR_NONE) {
                $this->model = isset($data->model)?$data->model : null;
                $this->focallength = isset($data->focallength)?$data->focallength : null;
                $this->fstop = isset($data->fstop)?$data->fstop : null;
                $this->exposuretime = isset($data->exposuretime)?$data->exposuretime : null;
                $this->iso = isset($data->iso)?$data->iso : null;
                $this->creation_date = isset($data->creation_date)?$data->creation_date : null;
            }
        }
    }

    public function toJson() {
        return json_encode($this);
    }

    /**
     * @param $filename string Path to the file which contains the data
     * @param $autorotate boolean defines if we autorotate the image to get width/height correctly
     * @return Exif
     */
    public static function extract($filename) {
        $exif = new self();
        if (function_exists('exif_read_data')) {

            $exifData = @exif_read_data($filename, 0, true);
            if (!isset($exifData["IFD0"]) ||
                !isset($exifData["EXIF"])) {
                return $exif;
            }

            if (isset($exifData["IFD0"]["Model"])) {
                $exif->model = $exifData["IFD0"]["Model"];
            }

            if (isset($exifData["COMPUTED"]["ApertureFNumber"])) {
                $exif->fstop = str_replace('f/','', $exifData["COMPUTED"]["ApertureFNumber"]);
            }

            if (isset($exifData["EXIF"]["ExposureTime"])) {
                $exif->exposuretime = self::exif_format_exposure($exifData["EXIF"]["ExposureTime"]);
            }

            if(isset($exifData["EXIF"]["ISOSpeedRatings"])) {
                $exif->iso = $exifData["EXIF"]["ISOSpeedRatings"];
            }

            if (isset($exifData["EXIF"]["FocalLength"])) {
                $focal_length = $exifData["EXIF"]["FocalLength"];
                $exif->focallength = sprintf('%.01f', self::exif_get_float($focal_length));
            }

            if (isset($exifData['IFD0']['Orientation'])) {
                $exif->orientation = $exifData['IFD0']['Orientation'];
                if ($exif->orientation == 6 || $exif->orientation == 8) {
                    $exif->has90DegreeRotation = true;
                }
            }

            if (isset($exifData["EXIF"]["DateTimeOriginal"])) {
                $creation_date = $exifData["EXIF"]["DateTimeOriginal"];
                if (!empty($creation_date)) {
                    $creation_date = str_replace(':', '', $creation_date);
                    $creation_date = str_replace(' ', '', $creation_date);
                    $exif->creation_date = $creation_date;
                }
            }
        }

        return $exif;
    }

    private static function exif_get_float($value) {
        $pos = strpos($value, '/');
        if ($pos === false) return (float) $value;
        $a = (float) substr($value, 0, $pos);
        $b = (float) substr($value, $pos+1);
        return ($b == 0) ? ($a) : ($a / $b);
    }

    private static function exif_format_exposure($value) {
        $v = explode('/', $value);
        if (count($v)==2) {
            if ($v[0] / $v[1] < 1) {
                return Pel::fmt('1/%d', $v[1] / $v[0]);
            } else {
                return Pel::fmt('%d', $v[0] / $v[1]);
            }
        }
        return $value;
    }


    /**
     * Converts a float into a fraction if the float is smaller than 1.
     *
     * @param $n
     * @param $tolerance
     * @return mixed|string
     */
    static function float2rat($n, $tolerance = 1.e-4) {
        $n = (float)$n;

        if ($n>=1 || $n<=0) {
            return $n;
        }
        $h1=1; $h2=0;
        $k1=0; $k2=1;
        $b = 1/$n;
        do {
            $b = 1/$b;
            $a = floor($b);
            $aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
            $aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
            $b = $b-$a;
        } while (abs($n-$h1/$k1) > $n*$tolerance);

        return "$h1/$k1";
    }

}

