<?php

namespace Vinteract\Resources;

use \Vinteract\Client;
use \Vinteract\Utils;

use \Vinteract\Payments\CardTokenRecord;

use \Illuminate\Database\Eloquent\Model;

use DateTime;

class User extends Model {
	
	/*
		Properties
	*/
	
	public $timestamps = false;
	
	protected $hidden = ["pivot"];
	
	protected $visible = [
		
		"id",
		"uuid",
		
		"name",
		"first_name",
		"last_name",
		"gender",
		"phone",
		"email",
		"dob",
		
		"country",
		"region",
		"region_short",
		"state",
		"state_short",
		"street_1",
		"street_2",
		"suburb",
		"city",
		"postcode",
		"lat",
		"lng",
		
		"notes",
		"favourites",
		
		"app_push_notifications",
		"web_push_notifications",
		"sms_notifications",
		
		"cards",
		"user_groups",
		"devices",
		
		"profile_picture",
		
	];
	
	protected $fillable = [
		"email",
		"password",
		"phone",
		"first_name",
		"last_name",
		"gender",
		"dob",
		"street_1",
		"street_2",
		"country",
		"region",
		"region_short",
		"suburb",
		"postcode",
		"lat",
		"lng",
		"terms_and_conditions",
		"active",
	];
	
	protected $appends = [
		"profile_picture",
	];
	
	protected $casts = [
		"notes" => "array",
		"favourites" => "array",
		"app_push_notifications" => "boolean",
		"web_push_notifications" => "boolean",
		"sms_notifications" => "boolean",
		"active" => "boolean",
	];
	
	protected $webPlatforms = ["Web", "web"];
	
	protected $appPlatforms = ["Android", "android", "iOS", "ios"];
	
	/*
		Overrides
	*/
	
	public function __construct($attributes = []) {
		
		parent::__construct($attributes);
		
		$this->setTable(Client::getName() . "_users");
		$this->setConnection(Client::getType());
		
	}
	
	protected static function boot() {
		
		parent::boot();
		
		static::setEventDispatcher(new \Illuminate\Events\Dispatcher());
		
		static::creating(function($model) {
			
			$model->uuid = Utils::generateUuid();
			
			$model->notes = '{"sermons":{},"events":{},"devotionals":{},"news":{},"newsletters":{},"verses":{},"prayer_requests":{}}';
			$model->favourites = '[]';
			
			$model->added = (new DateTime())->format("Y-m-d");
			$model->updated = (new DateTime())->format("Y-m-d");
			
		});
		
	}
	
	public function newQuery($excludeDeleted = true) {
		return parent::newQuery($excludeDeleted = true)
			->select()
			->selectRaw("CONCAT(first_name, ' ', last_name) AS name")
			->selectRaw("region AS state")
			->selectRaw("region_short AS state_short")
			->selectRaw("suburb AS city");
	}
	
	/*
		Mutators
	*/
	
	public function getProfilePictureAttribute() {
		$relative_path = "uploads/" . Client::getType() . "/" . Client::getName() . "/users_profile_pictures/{$this->id}.jpg";
		$file_path = Utils::getCmsPath($relative_path);
		if (file_exists($file_path)) {
			return Utils::getCmsUrl("{$relative_path}?time=" . time());
		}
		return null;
	}
	
	/*
		Scopes
	*/
	
	public function scopeIsRegistered($query) {
		$query->where("password", "!=", null)->where("password", "!=", "");
	}
	
	public function scopeIsNotRegistered($query) {
		$query->where("password", null)->orWhere("password", "=", "");
	}
	
	public function scopeHasWebPushSubscriptions($query) {
		
		//header("Content-Type: application/json"); echo json_encode($this->webPlatforms); exit();
		
		$constraint = function($query) {
			$devices_table = (new \Vinteract\Resources\UserDevice)->getTable();
			$query->whereIn("{$devices_table}.platform", $this->webPlatforms);
		};
		
		return $query->whereHas("devices", $constraint)
			->with(["devices" => $constraint]);
		
	}
	
	public function scopeHasAppPushSubscriptions($query) {
		
		$constraint = function($query) {
			$devices_table = (new \Vinteract\Resources\UserDevice)->getTable();
			$query->whereIn("{$devices_table}.platform", $this->appPlatforms);
		};
		
		return $query->whereHas("devices", $constraint)
			->with(["devices" => $constraint]);
		
	}
	
	public function scopeHasAppAndWebPushSubscriptions($query) {
		
		$constraint = function($query) {
			$devices_table = (new \Vinteract\Resources\UserDevice)->getTable();
			$query->whereIn("{$devices_table}.platform", array_merge($this->appPlatforms, $this->webPlatforms));
		};
		
		return $query->whereHas("devices", $constraint)
			->with(["devices" => $constraint]);
		
	}
	
	public function scopeHasPushSubscriptions($query, $app, $web) {
		
		$platforms = [];
		
		if ($app) {
			$platforms = array_merge($platforms, $this->appPlatforms);
		}
		
		if ($web) {
			$platforms = array_merge($platforms, $this->webPlatforms);
		}
		
		$constraint = function($query) use ($platforms) {
			$devices_table = (new \Vinteract\Resources\UserDevice)->getTable();
			$query->whereIn("{$devices_table}.platform", $platforms);
		};
		
		return $query->whereHas("devices", $constraint)
			->with(["devices" => $constraint]);
		
	}
	
	public function scopeHasMobileNumber($query) {
		$query->where("phone", "!=", null)->where("phone", "!=", "");
	}
	
	public function scopeAppPushNotificationsEnabled($query) {
		$query->where("app_push_notifications", 1);
	}
	
	public function scopeWebPushNotificationsEnabled($query) {
		$query->where("web_push_notifications", 1);
	}
	
	public function scopeSMSNotificationsEnabled($query) {
		$query->where("sms_notifications", 1);
	}
	
	/*
		Relationships
	*/
	
	public function cards() {
        return $this->hasMany(CardTokenRecord::class, "user_id", "id");
    }
	
	public function user_groups() {
		return $this->belongsToMany("\Vinteract\Resources\UserGroup", (Client::getName() . "_user_groups_users"), "user_id", "user_group_id")->minimalInformation();
	}
	
	public function devices() {
		return $this->hasMany("\Vinteract\Resources\UserDevice");
	}
	
}