<?php

class MTGImage implements JsonSerializable {

   const VALID_EXTENSIONS = array("gif", "jpg", "jpeg", "png", "webp");
   const MIME_TYPES = array("gif" => "image/gif", "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "png" => "image/png", "webp" => "image/webp");

   const MTGI_BOOLEANDB = 1000001;
   const MTGI_INCLUDEPLAYED = false;

   private $id = 0;
   private $filename = "";
   private $enabled = true;
   private $played = false;
   private $width = 0;
   private $height = 0;
   private $created = "1972-08-16 00:00:00";

   public function getId() {
      return $this->id;
   }

   public function getFileName() {
      return $this->filename;
   }

   public function getFileExtension() {
      return pathinfo($this->filename, PATHINFO_EXTENSION);
   }

   public function getEnabled($flag = 0) {
      switch ($flag) {
         case MTGImage::MTGI_BOOLEANDB:
            return ($this->enabled) ? 1 : 0;
            break;
         default:
            return $this->enabled;
            break;
      }
   }

   public function getPlayed($flag = 0) {
      switch ($flag) {
         case MTGImage::MTGI_BOOLEANDB:
            return ($this->played) ? 1 : 0;
            break;
         default:
            return $this->played;
            break;
      }
   }

   public function getWidth() {
      return $this->width;
   }

   public function getHeight() {
      return $this->height;
   }

   public function getDimensions() {
      return $this->width . "x" . $this->height;
   }

   public function getCreated() {
      return $this->created;
   }

   public function getAge() {
      $now = new DateTime();
      $mydate = new DateTime($this->getCreated());
      $interval = $mydate->diff($now);
      return $interval->d;
   }

   public function setId($value = null) {
      if ( is_null($value) ) return false;
      if ( !is_int($value) ) return false;
      if ( $value <= 0 ) return false;
      $this->id = $value;
      return true;
   }

   public function setFileName($value = "") {
      if ( $value == "" ) return false;
      if ( strpos($value, ".") === false ) return false;
      if ( strpos($value, "\"") !== false ) return false;
      $testvalue = basename($value);
      if ( $testvalue != $value ) return false;
      $extension = pathinfo($value, PATHINFO_EXTENSION);
      if ( !in_array(strtolower($extension), MTGImage::VALID_EXTENSIONS) ) return false;
      $this->filename = $value;
      return true;
   }

   public function setEnabled($value = null) {
      if ( is_null($value) ) return false;
      if ( is_int($value) && (($value == 1) || ($value == 0)) ) {
         $this->enabled = ($value == 1) ? true : false;
      } elseif ( is_bool($value) ) {
         $this->enabled = $value;
      } else {
         return false;
      }
      return true;
   }

   public function setPlayed($value = null) {
      if ( is_null($value) ) return false;
      if ( is_int($value) && (($value == 1) || ($value == 0)) ) {
         $this->played = ($value == 1) ? true : false;
      } elseif ( is_bool($value) ) {
         $this->played = $value;
      } else {
         return false;
      }
      return true;
   }

   public function setWidth($value = null) {
      if ( is_null($value) ) return false;
      if ( !is_int($value) || ($value < 0) ) return false;
      $this->width = $value;
      return true;
   }

   public function setHeight($value = null) {
      if ( is_null($value) ) return false;
      if ( !is_int($value) || ($value < 0) ) return false;
      $this->height = $value;
      return true;
   }

   public function renameImage($value = "") {
      $oldname = $this->getFileName();
      $conflictImage = MTGImage::getImageByFileName($value);
      if ( $conflictImage !== false ) return false;
      if ( !$this->setFileName($value) ) {
         return false;
      }
      if ( !is_file(IMAGEPATH . $oldname) ) {
         $this->setFileName($oldname);
         return false;
      }
      if ( !rename(IMAGEPATH . $oldname, IMAGEPATH . $value) ) {
         $this->setFileName($oldname);
         return false;
      }
      $this->save();
      return true;
   }

   public static function resetPlayed() {
      global $globaldbh;

      $query = "UPDATE images SET played = FALSE";
      $sth = $globaldbh->prepare($query);
      $sth->execute();
   }

   public static function getRandomImage(int|string $id = 0, bool $onlyUnplayed = true) {
      global $globaldbh;

      if ( is_string($id) ) $id = intval($id);
      if ( $id == 0 ) {
         if ( $onlyUnplayed ) {
            $query = "SELECT id FROM images WHERE enabled = TRUE AND played = FALSE ORDER BY RAND() LIMIT 1";
         } else {
            $query = "SELECT id FROM images WHERE enabled = TRUE ORDER BY RAND() LIMIT 1";
         }
         $sth = $globaldbh->prepare($query);
      } else {
         if ( $onlyUnplayed ) {
            $query = "SELECT id FROM images WHERE enabled = TRUE ";
            $query .= "AND PLAYED = FALSE AND id <> :id ORDER BY RAND() LIMIT 1";
         } else {
            $query = "SELECT id FROM images WHERE enabled = TRUE ";
            $query .= "AND id <> :id ORDER BY RAND() LIMIT 1";
         }
         $sth = $globaldbh->prepare($query);
         $sth->bindValue(":id", intval($id), PDO::PARAM_INT);
      }
      $sth->execute();
      if ( $row = $sth->fetch(PDO::FETCH_ASSOC) ) {
         return new MTGImage($row["id"]);
      } else {
         return false;
      }
   }

   public static function getImageByFileName($value = "") {
      global $globaldbh;

      $query = "SELECT id FROM images WHERE BINARY filename=:filename";
      $sth = $globaldbh->prepare($query);
      $sth->bindValue(":filename", $value, PDO::PARAM_STR);
      $sth->execute();
      if ( $row = $sth->fetch(PDO::FETCH_ASSOC) ) {
         return new MTGImage($row["id"]);
      } else {
         return false;
      }
   }

   public static function getList() {
      global $globaldbh;

      $query = "SELECT id FROM images ORDER BY LOWER(filename)";
      $sth = $globaldbh->prepare($query);
      $sth->execute();
      $thelist = array();
      while ( $row = $sth->fetch(PDO::FETCH_ASSOC) ) {
         $thelist[] = new MTGImage($row["id"]);
      }
      return $thelist;
   }

   public function jsonSerialize(): mixed {
      if ( $this->getHeight() < 400 ) {
         $size = "small";
      } elseif ( $this->getHeight() < 700 ) {
         $size = "medium";
      } else {
         $size = "large";
      }
      return [
         'id' => $this->getId(),
         'filename' => $this->getFileName(),
         'title' => pathinfo($this->getFileName(), PATHINFO_FILENAME),
         'enabled' => $this->getEnabled(),
         'played' => $this->getPlayed(),
         'width' => $this->getWidth(),
         'height' => $this->getHeight(),
         'dimensions' => $this->getDimensions(),
         'created' => $this->getCreated(),
         'age' => $this->getAge(),
         'size' => $size,
      ];
   }

   public function delete() {
      global $globaldbh;

      if ( is_file("images/" . $this->getFileName()) ) {
         if ( !unlink("images/" . $this->getFileName()) ) return false;
      }
      if ( $this->getId() == 0 ) return false;
      $query = "DELETE FROM images WHERE id=:id";
      $sth = $globaldbh->prepare($query);
      $sth->bindValue(":id", (int) $this->getId(), PDO::PARAM_INT);
      $sth->execute();
      $this->id = 0;
      return true;
   }

   public function save() {
      global $globaldbh;

      $query = "INSERT INTO images (id, filename, width, height) VALUES(:id, :filename, :width, :height) ON DUPLICATE KEY UPDATE filename=:filename, enabled=:enabled, played=:played, width=:width, height=:height";
      $sth = $globaldbh->prepare($query);
      $sth->bindValue(":id", (int) $this->getId(), PDO::PARAM_INT);
      $sth->bindValue(":filename", $this->getFileName(), PDO::PARAM_STR);
      $sth->bindValue(":enabled", (int) $this->getEnabled(MTGImage::MTGI_BOOLEANDB), PDO::PARAM_INT);
      $sth->bindValue(":played", (int) $this->getPlayed(MTGImage::MTGI_BOOLEANDB), PDO::PARAM_INT);
      $sth->bindValue(":width", (int) $this->getWidth(), PDO::PARAM_INT);
      $sth->bindValue(":height", (int) $this->getHeight(), PDO::PARAM_INT);
      $sth->execute();
      if ( $this->getId() == 0 ) $this->setId($globaldbh->lastInsertId());
      return;
   }

   public function __construct($imgid = 0) {
      global $globaldbh;

      if ( !is_int($imgid) || $imgid == 0 ) return;
      $query = "SELECT id, filename, enabled, played, width, height, created FROM images where id=:id";
      $sth = $globaldbh->prepare($query);
      $sth->bindValue(":id", (int) $imgid, PDO::PARAM_INT);
      $sth->execute();
      if ( $row = $sth->fetch(PDO::FETCH_ASSOC) ) {
         $this->setId($row["id"]);
         $this->setFileName($row["filename"]);
         $this->setEnabled($row["enabled"]);
         $this->setPlayed($row["played"]);
         $this->setWidth($row["width"]);
         $this->setHeight($row["height"]);
         $this->created = $row["created"];
      }
   }
}

// vim:ts=3 sw=3 et:
