<commit_before><?php

namespace Models\Mship;

use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use \Carbon\Carbon;
use \Models\Mship\Account\Email as AccountEmail;
use \Models\Mship\Account\Qualification as AccountQualification;
use \Models\Sys\Token as SystemToken;
use \Models\Mship\Role as RoleData;
use \Models\Mship\Permission as PermissionData;
use \Models\Mship\Account\Note as AccountNoteData;
use \Models\Teamspeak\Registration;
use \Models\Sys\Notification as SysNotification;

class Account extends \Models\aTimelineEntry implements UserInterface {

    use UserTrait, SoftDeletingTrait;

    protected $table = "mship_account";
    protected $primaryKey = "account_id";
    public $incrementing = false;
    protected $dates = ['auth_extra_at', 'last_login', 'joined_at', 'created_at', 'updated_at', 'deleted_at'];
    protected $fillable = ['account_id', 'name_first', 'name_last'];
    protected $attributes = ['name_first' => '', 'name_last' => '', 'status' => self::STATUS_ACTIVE, 'last_login_ip' => '127.0.0.1'];
    protected $doNotTrack = ['session_id', 'auth_extra', 'auth_extra_id', 'cert_checked_at', 'last_login', 'remember_token'];

    const STATUS_ACTIVE = 0; //b"00000";
    const STATUS_SYSTEM_BANNED = 1; //b"0001";
    const STATUS_NETWORK_SUSPENDED = 2; //b"0010";
    const STATUS_INACTIVE = 4; //b"0100";
    const STATUS_LOCKED = 8; //b"1000";
    const STATUS_SYSTEM = 8; //b"1000"; // Alias of LOCKED

    public static function getStatusDescription($value) {
        switch ($value) {
            case self::STATUS_ACTIVE:
                return "Active";
            case self::STATUS_SYSTEM_BANNED:
                return "Banned (LOCAL)";
            case self::STATUS_NETWORK_SUSPENDED:
                return "Suspended (NETWORK)";
            case self::STATUS_INACTIVE:
                return "Inactive";
            case self::STATUS_LOCKED:
            case self::STATUS_SYSTEM:
                return "Locked/System";
            default:
                return "Unknown Status";
        }
    }

    public static function eventCreated($model, $extra=null, $data=null){
        parent::eventCreated($model, $extra, $data);

        // Add the user to the default role.
        $defaultRole = RoleData::isDefault()->first();
        if($defaultRole){
            $model->roles()->attach($defaultRole);
        }

        // Generate an email to the user to advise them of their new account at VATUK.
        \Models\Sys\Postmaster\Queue::queue("MSHIP_ACCOUNT_CREATED", $model->account_id, VATUK_ACCOUNT_SYSTEM, $model->toArray());
    }

    public static function scopeIsSystem($query){
        return $query->where(\DB::raw(self::STATUS_SYSTEM."&`status`"), "=", self::STATUS_SYSTEM);
    }

    public static function scopeIsNotSystem($query){
        return $query->where(\DB::raw(self::STATUS_SYSTEM."&`status`"), "!=", self::STATUS_SYSTEM);
    }

    public static function scopeWithIp($query, $ip){
        return $query->where("last_login_ip", "=", ip2long($ip));
    }

    public function dataChanges(){
        return $this->morphMany("\Models\Sys\Data\Change", "model")->orderBy("created_at", "DESC");
    }

    public function emails() {
        return $this->hasMany("\Models\Mship\Account\Email", "account_id", "account_id");
    }

    public function messagesReceived() {
        return $this->hasMany("\Models\Sys\Postmaster\Queue", "recipient_id", "account_id")->orderBy("created_at", "DESC")->with("sender");
    }

    public function messagesSent() {
        return $this->hasMany("\Models\Sys\Postmaster\Queue", "sender_id", "account_id")->orderBy("created_at", "DESC")->with("recipient");
    }

    public function notes() {
        return $this->hasMany("\Models\Mship\Account\Note", "account_id", "account_id")->orderBy("created_at", "DESC");
    }

    public function noteWriter() {
        return $this->hasMany("\Models\Mship\Account\Note", "writer_id", "account_id");
    }

    public function tokens() {
        return $this->morphMany("\Models\Sys\Token", "related");
    }

    public function qualifications() {
        return $this->hasMany("\Models\Mship\Account\Qualification", "account_id", "account_id")->orderBy("created_at", "DESC")->with("qualification");
    }

    public function roles(){
        return $this->belongsToMany("\Models\Mship\Role", "mship_account_role")->with("permissions")->withTimestamps();
    }

    public function states() {
        return $this->hasMany("\Models\Mship\Account\State", "account_id", "account_id")->orderBy("created_at", "DESC");
    }

    public function ssoEmails() {
        return $this->hasMany("\Models\Sso\Email", "account_id", "account_id");
    }

    public function ssoTokens() {
        return $this->hasMany("\Models\Sso\Token", "account_id", "account_id");
    }

    public function security() {
        return $this->hasMany("\Models\Mship\Account\Security", "account_id", "account_id")->orderBy("created_at", "DESC");
    }

    public function teamspeakAliases() {
        return $this->hasMany("\Models\Teamspeak\Alias", "account_id", "account_id");
    }

    public function teamspeakBans() {
        return $this->hasMany("\Models\Teamspeak\Ban", "account_id", "account_id");
    }

    public function teamspeakRegistrations() {
        return $this->hasMany("\Models\Teamspeak\Registration", "account_id", "account_id");
    }

    public function readNotifications(){
        return $this->belongsToMany("\Models\Sys\Notification", "sys_notification_read", "account_id", "notification_id")->orderBy("status", "DESC")->orderBy("effective_at", "DESC")->withTimestamps();
    }

    public function getUnreadNotificationsAttribute(){
        // Get all read notifications
        $readNotifications = $this->readNotifications;

        // Get all notifications
        $allNotifications = SysNotification::published()
                                           ->since($this->created_at)
                                           ->orderBy("status", "DESC")
                                           ->orderBy("effective_at", "DESC")
                                           ->get();

        // The difference between the two MUST be the ones that are unread, right?<commit_msg>TEMP: Removed lower limit on notifications.<commit_after><?php

namespace Models\Mship;

use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use \Carbon\Carbon;
use \Models\Mship\Account\Email as AccountEmail;
use \Models\Mship\Account\Qualification as AccountQualification;
use \Models\Sys\Token as SystemToken;
use \Models\Mship\Role as RoleData;
use \Models\Mship\Permission as PermissionData;
use \Models\Mship\Account\Note as AccountNoteData;
use \Models\Teamspeak\Registration;
use \Models\Sys\Notification as SysNotification;

class Account extends \Models\aTimelineEntry implements UserInterface {

    use UserTrait, SoftDeletingTrait;

    protected $table = "mship_account";
    protected $primaryKey = "account_id";
    public $incrementing = false;
    protected $dates = ['auth_extra_at', 'last_login', 'joined_at', 'created_at', 'updated_at', 'deleted_at'];
    protected $fillable = ['account_id', 'name_first', 'name_last'];
    protected $attributes = ['name_first' => '', 'name_last' => '', 'status' => self::STATUS_ACTIVE, 'last_login_ip' => '127.0.0.1'];
    protected $doNotTrack = ['session_id', 'auth_extra', 'auth_extra_id', 'cert_checked_at', 'last_login', 'remember_token'];

    const STATUS_ACTIVE = 0; //b"00000";
    const STATUS_SYSTEM_BANNED = 1; //b"0001";
    const STATUS_NETWORK_SUSPENDED = 2; //b"0010";
    const STATUS_INACTIVE = 4; //b"0100";
    const STATUS_LOCKED = 8; //b"1000";
    const STATUS_SYSTEM = 8; //b"1000"; // Alias of LOCKED

    public static function getStatusDescription($value) {
        switch ($value) {
            case self::STATUS_ACTIVE:
                return "Active";
            case self::STATUS_SYSTEM_BANNED:
                return "Banned (LOCAL)";
            case self::STATUS_NETWORK_SUSPENDED:
                return "Suspended (NETWORK)";
            case self::STATUS_INACTIVE:
                return "Inactive";
            case self::STATUS_LOCKED:
            case self::STATUS_SYSTEM:
                return "Locked/System";
            default:
                return "Unknown Status";
        }
    }

    public static function eventCreated($model, $extra=null, $data=null){
        parent::eventCreated($model, $extra, $data);

        // Add the user to the default role.
        $defaultRole = RoleData::isDefault()->first();
        if($defaultRole){
            $model->roles()->attach($defaultRole);
        }

        // Generate an email to the user to advise them of their new account at VATUK.
        \Models\Sys\Postmaster\Queue::queue("MSHIP_ACCOUNT_CREATED", $model->account_id, VATUK_ACCOUNT_SYSTEM, $model->toArray());
    }

    public static function scopeIsSystem($query){
        return $query->where(\DB::raw(self::STATUS_SYSTEM."&`status`"), "=", self::STATUS_SYSTEM);
    }

    public static function scopeIsNotSystem($query){
        return $query->where(\DB::raw(self::STATUS_SYSTEM."&`status`"), "!=", self::STATUS_SYSTEM);
    }

    public static function scopeWithIp($query, $ip){
        return $query->where("last_login_ip", "=", ip2long($ip));
    }

    public function dataChanges(){
        return $this->morphMany("\Models\Sys\Data\Change", "model")->orderBy("created_at", "DESC");
    }

    public function emails() {
        return $this->hasMany("\Models\Mship\Account\Email", "account_id", "account_id");
    }

    public function messagesReceived() {
        return $this->hasMany("\Models\Sys\Postmaster\Queue", "recipient_id", "account_id")->orderBy("created_at", "DESC")->with("sender");
    }

    public function messagesSent() {
        return $this->hasMany("\Models\Sys\Postmaster\Queue", "sender_id", "account_id")->orderBy("created_at", "DESC")->with("recipient");
    }

    public function notes() {
        return $this->hasMany("\Models\Mship\Account\Note", "account_id", "account_id")->orderBy("created_at", "DESC");
    }

    public function noteWriter() {
        return $this->hasMany("\Models\Mship\Account\Note", "writer_id", "account_id");
    }

    public function tokens() {
        return $this->morphMany("\Models\Sys\Token", "related");
    }

    public function qualifications() {
        return $this->hasMany("\Models\Mship\Account\Qualification", "account_id", "account_id")->orderBy("created_at", "DESC")->with("qualification");
    }

    public function roles(){
        return $this->belongsToMany("\Models\Mship\Role", "mship_account_role")->with("permissions")->withTimestamps();
    }

    public function states() {
        return $this->hasMany("\Models\Mship\Account\State", "account_id", "account_id")->orderBy("created_at", "DESC");
    }

    public function ssoEmails() {
        return $this->hasMany("\Models\Sso\Email", "account_id", "account_id");
    }

    public function ssoTokens() {
        return $this->hasMany("\Models\Sso\Token", "account_id", "account_id");
    }

    public function security() {
        return $this->hasMany("\Models\Mship\Account\Security", "account_id", "account_id")->orderBy("created_at", "DESC");
    }

    public function teamspeakAliases() {
        return $this->hasMany("\Models\Teamspeak\Alias", "account_id", "account_id");
    }

    public function teamspeakBans() {
        return $this->hasMany("\Models\Teamspeak\Ban", "account_id", "account_id");
    }

    public function teamspeakRegistrations() {
        return $this->hasMany("\Models\Teamspeak\Registration", "account_id", "account_id");
    }

    public function readNotifications(){
        return $this->belongsToMany("\Models\Sys\Notification", "sys_notification_read", "account_id", "notification_id")->orderBy("status", "DESC")->orderBy("effective_at", "DESC")->withTimestamps();
    }

    public function getUnreadNotificationsAttribute(){
        // Get all read notifications
        $readNotifications = $this->readNotifications;

        // Get all notifications
        $allNotifications = SysNotification::published()
                                           //->since($this->created_at) TODO: Add back AFTER we've launched new T&Cs.
                                           ->orderBy("status", "DESC")
                                           ->orderBy("effective_at", "DESC")
                                           ->get();

        // The difference between the two MUST be the ones that are unread, right?
{'fraction_non_alphanumeric': 0.15007874015748032, 'fraction_numerical': 0.005984251968503937, 'mean_word_length': 3.1317501626545217, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6617722', 'n_tokens_mistral': 3820, 'n_tokens_neox': 3670, 'n_words': 750}