<?php

class Agro_Utils_Watermark {
    private $_font = '';
    private $_fontSize = null;
    private $_fontColor = null;
    private $_imagePath;
    private $_imageJpeg = null;
    private $_exif = array();
    private $_gpsLatitude = '';
    private $_gpsLongitude = '';
    private $_dateTime = '';
    private $_imageLength = null;
    private $_imageWidth = null;

    public function __construct(string $image_path) {
        if (file_exists($image_path) && (mime_content_type($image_path) == 'image/jpeg') && (filesize($image_path) > 0)) {
            $this->_imagePath = $image_path;
            $res = imagecreatefromjpeg($this->_imagePath);

            if (is_resource($res)) {
                $this->_imageJpeg = $res;
                $this->getExifFromImage();
            } else {
                throw new InvalidArgumentException(
                    die("Erro ao gerar imagem, verifique o caminho ou imagem informados.")
                );
            }
        }
    }

    //se não passar valores de cor ficará o texto padrão em branco #FFFFFF
    public function setColorText(int $r=255, int $g=255, int $b=255) {
        try {
            $this->_fontColor = imagecolorallocate($this->_imageJpeg, $r, $g, $b);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }

    public function generateWatermark() : bool {
        $wm = null;
        if (is_resource($this->_imageJpeg)) {
            if ($this->_exif) {
                $this->setGPSData();
                $this->setDateTime();
                $this->setColorText();
                $this->setImageLength();
                $this->setImageWidth();
                
                $diagonal = sqrt(pow($this->_imageWidth,2) + pow($this->_imageLength,2))/1000;

                // 1 inch = 96 pixels
                $fs = floor(($diagonal * 96)/10) + 3;
                $this->setFontSize(
                    floor(($diagonal * 96)/10) + 3
                );

                $info = htmlentities($this->_gpsLatitude.' '.$this->_gpsLongitude."\n".$this->_dateTime);
                
                if ($this->_imageWidth > $this->_imageLength) {
                    $x = floor($this->_imageWidth * 0.72);
                    $y = floor($this->_imageLength * 0.95);
                } else {
                    $x = floor($this->_imageWidth * 0.50);
                    $y = floor($this->_imageLength * 0.97);
                }
                
                if ($this->_font != '') {
                    $wm = imagettftext(
                        $this->_imageJpeg,
                        $this->_fontSize,
                        0,
                        $x,
                        $y,
                        $this->_fontColor,
                        $this->_font,
                        $info
                    );
                } else {
                    $wm = imagestring(
                        $this->_imageJpeg,
                        5,
                        $x,
                        $y,
                        $info,
                        $this->_fontColor
                    );
                }

                if ($wm) {
                    $orientation = $this->_exif['IFD0']['Orientation'];
                    
                    if ($orientation != 1) {
                        $deg = 0;

                        switch ($orientation) {
                            case 3: $deg = 180; break;
                            case 6: $deg = 270; break;
                            case 8: $deg = 90; break;
                        }

                        if ($deg) {
                            $this->_imageJpeg = imagerotate($this->_imageJpeg, $deg, 0);
                        }
                    }

                    if (imagejpeg($this->_imageJpeg, $this->_imagePath)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    private function getExifFromImage() : void {
        if (!is_null($this->_imageJpeg)) {
            $temp = exif_read_data($this->_imagePath, 0, true);
            if (is_array($temp)) {
                $this->_exif = $temp;
            }
        } else {
            throw new Exception("Image não carregada, verifique!");
        }
    }

    public function showExif() : array {
            return $this->_exif;
    }

    private function setDateTime() : void {
        if ($this->_exif['IFD0']) {
            $dt = explode(' ',$this->_exif['IFD0']['DateTime']);
        } elseif ($this->_exif['DateTime']) {
            $dt = explode(' ',$this->_exif['IFD0']['DateTime']);
        } else {} 
        
        if (count($dt)>0) {
            list($ano, $mes, $dia) = explode(':', $dt[0]);
            $this->_dateTime = $dia.'/'.$mes.'/'.$ano.' '.$dt[1];
        }
    }

    public function getDateTime() : string {
        return $this->_dateTime;
    }

    private function setGPSData() : void {
        if (is_array($this->_exif['GPS']) && ($this->_exif['GPS']['GPSLatitudeRef'])) {
            $gps = $this->_exif['GPS'];
        } elseif ($this->_exif['GPSLatitude'] != '') {
            $gps['GPSLatitude'] = $this->_exif['GPSLatitude'];
            $gps['GPSLatitudeRef'] = $this->_exif['GPSLatitudeRef'];
            $gps['GPSLongitude'] = $this->_exif['GPSLongitude'];
            $gps['GPSLongitudeRef'] = $this->_exif['GPSLongitudeRef'];
        } else {
            $gps = '';
        }

        if (is_array($gps)){
            $lat_grau = explode('/', $gps['GPSLatitude'][0])[0];
            $lon_grau = explode('/', $gps['GPSLongitude'][0])[0];
            $lat_min = explode('/', $gps['GPSLatitude'][1])[0];
            $lon_min = explode('/', $gps['GPSLongitude'][1])[0];
            list($lat_dividendo,$lat_divisor) = explode('/', $gps['GPSLatitude'][2]);
            list($lon_dividendo,$lon_divisor) = explode('/', $gps['GPSLongitude'][2]);

            $this->_gpsLatitude = $lat_grau."° ".$lat_min."' ".round(($lat_dividendo/$lat_divisor),2).'"'.$gps['GPSLatitudeRef'];

            $this->_gpsLongitude = $lon_grau."° ".$lon_min."' ".round(($lon_dividendo/$lon_divisor),2).'"'.$gps['GPSLongitudeRef'];
        }
    }

    public function getLatitude() : string {
        return $this->_gpsLatitude;
    }

    public function getLongitude() : string {
        return $this->_gpsLongitude;
    }

    public function setFont(string $font_path) : void {
        if (file_exists($font_path)) {
            $this->_font = $font_path;
        }
    }

    public function getFont() : string {
        return $this->_font;
    }

    public function getFontSize() : Int {
        return $this->_fontSize;
    }

    public function setFontSize(int $size) {
        $this->_fontSize = $size;
    }

    private function setImageLength() : void {
        if ($this->_exif['COMPUTED']['Height'] != '') {
            $this->_imageLength = $this->_exif['COMPUTED']['Height'];
        } else {
            throw new Exception('ERRO! Não foi possível encontrar a altura da imagem');
        }
    }

    private function setImageWidth() : void {
        if ($this->_exif['COMPUTED']['Width'] != '') {
            $this->_imageWidth = $this->_exif['COMPUTED']['Width'];
        } else {
            throw new Exception('ERRO! Não foi possível encontrar a largura da imagem');
        }
    }
}