<?php
namespace SPAATG\Notices;

class NoticeModel //extends ShortPixelModel
{
  public $message; // The message we want to convey.
  public $details = array(); // extra details, like the files involved. Something could be hideable in the future.
  public $code;

  private $id = null; // used for persistent messages.
  protected $viewed = false; // was this notice viewed?
  protected $is_persistent = false;  // This is a fatal issue, display until something was fixed.
  protected $is_dismissed = false; // for persistent notices,
  protected $suppress_until = null;
  protected $suppress_period = -1;
	protected $include_screens = array();
	protected $exclude_screens = array();
  public $is_removable = true; // if removable, display a notice dialog with red X or so.
  public $messageType = self::NOTICE_NORMAL;

  public $notice_action; // empty unless for display. Ajax action to talk back to controller.
  protected $callback; // empty unless callback is needed

  public static $icons = array();

  const NOTICE_NORMAL = 1;
  const NOTICE_ERROR = 2;
  const NOTICE_SUCCESS = 3;
  const NOTICE_WARNING = 4;

  /** Use this model in conjunction with NoticeController, do not call directly */
  public function __construct($message, $messageType = self::NOTICE_NORMAL)
  {
      $this->message = $message;
      $this->messageType = $messageType;
  }

  public function isDone()
  {
    // check suppressed
    if ($this->is_dismissed && ! is_null($this->suppress_until))
    {
        if (time() >= $this->suppress_until)
        {
            $this->is_persistent = false; // unpersist, so it will be cleaned and dropped.
        }
    }

    if ($this->viewed && ! $this->is_persistent)
      return true;
    else
      return false;
  }

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

  public function isPersistent()
  {
     return $this->is_persistent;
  }

  public function isDismissed()
  {
    return $this->is_dismissed;
  }

  public function dismiss()
  {
     $this->is_dismissed = true;
     $this->suppress_until = time() + $this->suppress_period;
  }

  public function unDismiss()
  {
    $this->is_dismissed = false;
  }

  public function setDismissedUntil($timestamp)
  {
    $this->suppress_until = $timestamp;
  }

  /** Support for extra information beyond the message.
  * Can help to not overwhelm users w/ the same message but different file /circumstances.
   */
  public function addDetail($detail, $clean = false)
  {
      if ($clean)
        $this->details = array();

      if (! in_array($detail, $this->details) )
        $this->details[] = $detail;
  }

	/**
	* @param $method String Include or Exclude
	* @param $includes String|Array  Screen Names to Include / Exclude either string, or array
	*/
	public function limitScreens($method, $screens)
	{
			if ($method == 'exclude')
			{
				 $var = 'exclude_screens';
			}
			else {
				  $var = 'include_screens';
			}

			if (is_array($screens))
			{
				 $this->$var = array_merge($this->$var, $screens);
			}
			else {
				 $this->{$var}[] = $screens; // strange syntax is PHP 5.6 compat.
			}
	}

	/* Checks if Notice is allowed on this screen
	* @param @screen_id String The screen Id to check ( most likely current one, via EnvironmentModel)
	*/
	public function checkScreen($screen_id)
	{
			if (in_array($screen_id, $this->exclude_screens))
			{
				 return false;
			}
			if (in_array($screen_id, $this->include_screens))
			{
				 return true;
			}

			// if include is set, don't show if not screen included.
			if (count($this->include_screens) == 0)
			{
				return true;
			}
			else {
				return false;
			}
	}


  /** Set a notice persistent. Meaning it shows every page load until dismissed.
  * @param $key Unique Key of this message. Required
  * @param $suppress When dismissed do not show this message again for X amount of time. When -1 it will just be dropped from the Notices and not suppressed
  */
  public function setPersistent($key, $suppress = -1, $callback = null)
  {
      $this->id = $key;
      $this->is_persistent = true;
      $this->suppress_period = $suppress;
      if ( ! is_null($callback) && is_callable($callback))
      {
        $this->callback = $callback;
      }
  }

  public static function setIcon($notice_type, $icon)
  {
    switch($notice_type)
    {
      case 'error':
        $type = self::NOTICE_ERROR;
      break;
      case 'success':
        $type = self::NOTICE_SUCCESS;
      break;
      case 'warning':
        $type = self::NOTICE_WARNING;
      break;
      case 'normal':
      default:
        $type = self::NOTICE_NORMAL;
      break;
    }
    self::$icons[$type] = $icon;
  }

	public function _debug_getvar($var)
	{
		 if (property_exists($this, $var))
		 {
			  return $this->$var;
		 }
	}

  private function checkIncomplete($var)
  {
     return ($var instanceof \__PHP_Incomplete_Class);
  }

  public function getForDisplay()
  {
    $this->viewed = true;
    $class = 'shortpixel shortpixel-notice ';

    $icon = '';

    if ($this->callback)
    {
      if (is_array($this->callback))
      {
        foreach($this->callback as $part)
        {
          if ($this->checkIncomplete($part) === true)
          {
              return false;
          }
        }
      } elseif (is_object($this->callback))
      {
            if ($this->checkIncomplete($part) === true)
              return false;
      }

			if (! is_callable($this->callback))
			{
				 return;
			}
			else {
				$return = call_user_func($this->callback, $this);
        if ($return === false) // don't display is callback returns false explicitly.
         return;

			}
    }

    switch($this->messageType)
    {
      case self::NOTICE_ERROR:
        $class .= 'notice-error ';
        $icon = isset(self::$icons[self::NOTICE_ERROR]) ? self::$icons[self::NOTICE_ERROR] : '';
        //$icon = 'scared';
      break;
      case self::NOTICE_SUCCESS:
        $class .= 'notice-success ';
        $icon = isset(self::$icons[self::NOTICE_SUCCESS]) ? self::$icons[self::NOTICE_SUCCESS] : '';
      break;
      case self::NOTICE_WARNING:
        $class .= 'notice-warning ';
        $icon = isset(self::$icons[self::NOTICE_WARNING]) ? self::$icons[self::NOTICE_WARNING] : '';
      break;
      case self::NOTICE_NORMAL:
         $class .= 'notice-info ';
         $icon = isset(self::$icons[self::NOTICE_NORMAL]) ? self::$icons[self::NOTICE_NORMAL] : '';
      break;
      default:
        $class .= 'notice-info ';
        $icon = '';
      break;
    }


    if ($this->is_removable)
    {
      $class .= 'is-dismissible ';
    }

    if ($this->is_persistent)
    {
      $class .= 'is-persistent ';
    }

	    $id = ! is_null($this->id) ?  $this->id : uniqid();
	    $id = sanitize_html_class( $id );

	    $allowed_icon_html = [
	      'img' => [
	        'src' => true,
	        'height' => true,
	        'width' => true,
	        'alt' => true,
	        'class' => true,
	      ],
	      'span' => [
	        'class' => true,
	      ],
	    ];

	    $output = sprintf(
	      '<div id="%1$s" class="%2$s" data-persistent="%5$s" data-notice-action="%6$s"><span class="icon">%3$s</span><span class="content">%4$s',
	      esc_attr( $id ),
	      esc_attr( $class ),
	      wp_kses( $icon, $allowed_icon_html ),
	      wp_kses_post( $this->message ),
          $this->is_persistent ? '1' : '0',
          esc_attr( (string) $this->notice_action )
	    );

    if ($this->hasDetails())
    {

      $details = sprintf('<div class="details-wrapper">
            <input type="checkbox" name="detailhider" id="check-%s">
            <label for="check-%s"  class="show-details"><span>%s</span>
	            </label>
	             <div class="detail-content-wrapper"><p class="detail-content">%s</p></div>
	          <label for="check-%s" class="hide-details"><span>%s</span></label>
	            </div>',
	        esc_attr( $id ),
	        esc_attr( $id ),
	        esc_html__( 'See Details', 'shortpixel-ai-alt-text-generator' ),
	        $this->parseDetails(),
	        esc_attr( $id ),
	        esc_html__( 'Hide Details', 'shortpixel-ai-alt-text-generator' )
	      );

      $output .= $details;

    }
    $output .= "</span>";

    if ($this->is_removable)
    {
	        $output .= sprintf(
	          '<button type="button" id="button-%1$s" class="notice-dismiss" data-dismiss="%2$s" ><span class="screen-reader-text">%3$s</span></button>',
	          esc_attr( $id ),
	          esc_attr( $this->suppress_period ),
	          esc_html__( 'Dismiss this notice', 'shortpixel-ai-alt-text-generator' )
	        );

    }

    $output .= "</div>";
    return $output;
  }

  protected function hasDetails()
  {
     if (is_array($this->details) && count($this->details) > 0)
      return true;
    else
      return false;
  }

  protected function parseDetails()
  {
	      return implode( '<br>', array_map( 'esc_html', $this->details ) );
  }

}
