<?php
/********************************************************************************
 * (c)1337 aheadware.com - All rights reserved
 ********************************************************************************/


class TB_Server_Control_Profile {

    /**
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     */
    public static function get( TB_Server_Core_RequestData $params )
    {
        $resp = new TB_Server_Core_Response();

        /** @var TB_Shared_Ent_TeamData_Profile $sessionProfile */
        $sessionProfile = TB_Server_Core_Session::get()->getProfile();

        $includePremiumLogs = $params->get( 'includePremiumLogs', false );

        /** @var TB_Shared_Ent_TeamData_Profile $profile */
        $profile = TB_Shared_Ent_TeamData_Profile::get( $params->get( 'profile_id' ) );

        if ( $profile->team_id != $sessionProfile->team_id )
        {
            throw new Exception( 'Cannot get profile from foreign team member.' );
        }

        /** @var TB_Shared_Ent_Core_Account $account */
        $account = TB_Shared_Ent_Core_Account::get( $profile->account_id );

        if ( $includePremiumLogs )
        {
            /** @var TB_Shared_Ent_TeamData_Team $team */
            $team = TB_Shared_Ent_TeamData_Team::get( $profile->team_id );

            $validPremiumLogs = TB_Shared_Ent_TeamData_PremiumLog::getValidPremiumLogsForTeam( $team );

            $resp->addData( 'premium_logs', $validPremiumLogs );
        }

        $resp->addData( 'profile',  $profile );
        $resp->addData( 'account', $account );
        $resp->addData( 'profile_timestamp', $profile->getTimestamps() );

        return $resp;
    }

    /**
     * Get all profiles of curren user
     *
     * @param TB_Server_Core_RequestData $params
     *
     * @return TB_Server_Core_Response
     */
    public static function getAll( TB_Server_Core_RequestData $params ) {
        $resp = new TB_Server_Core_Response();

        /** @var TB_Shared_Ent_TeamData_Profile $profile */
        $profile = TB_Server_Core_Session::get()->getProfile();

        if ( isset( $profile ) ) {
            $profiles = TB_Shared_Ent_TeamData_Profile::getByAccountId( $profile->account_id );
            $resp->addData( 'profiles', $profiles );
        } else {
            $resp->addData( 'profiles', null );
        }

        return $resp;
    }


    /**
     * Change profile
     *
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     */
    public static function change( TB_Server_Core_RequestData $params ) {
        $resp = new TB_Server_Core_Response();

        // Current onliner
        $currentSession = TB_Server_Core_Session::get();
        $currentProfile = $currentSession->getProfile();

        // Resolve new profile to change to
        /** @var TB_Shared_Ent_TeamData_Profile $newProfile */
        $newProfile = TB_Shared_Ent_TeamData_Profile::get( $params->get( 'profile_id' ) );
        if ( !isset( $newProfile ) || $newProfile->account_id != $currentProfile->account_id ) {
            throw new Exception( "Invalid try to change profile" );
        }

        $profiles = TB_Shared_Ent_TeamData_Profile::getByAccountId( $currentProfile->account_id );
        $teams = array();
        foreach( $profiles as $p ) {
            array_push( $teams, TB_Shared_Ent_TeamData_Team::get( $p->team_id ) );
        }

        $resp->addData( 'profiles', $profiles );
        $resp->addData( 'teams', $teams );

        /** @var TB_Shared_Ent_Core_Session $newSession */
        $newSession = TB_Shared_Ent_Core_Session::getByAccountId( $currentProfile->account_id );
        $newSession->profile_id = $newProfile->id;
        $newSession->token = TB_Server_Core_Session::generateToken();
        $newSession->save();
        TB_Server_Core_Session::get()->destory();
        TB_Server_Core_Session::get()->init( $newSession );

        $resp->addData( 'profile', $newProfile );
        $resp->addData( 'session', $newSession );

        return $resp;
    }

    /**
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     * @throws Exception
     */
    public static function update( TB_Server_Core_RequestData $params ) {
        $resp = new TB_Server_Core_Response();

        // Check
        $profile = TB_Server_Core_Session::get()->getProfile();
        if ( $profile->isPlayer() && $profile->id != $params->get( 'id' ) ) {
            throw new Exception( 'Not allowed to change profile', TB_Server_Core_Response::CODE_INVALID_CALL );
        }

        /** @var TB_Shared_Ent_TeamData_Profile $profileToUpdate */
        $profileToUpdate = TB_Shared_Ent_TeamData_Profile::get( $params->get( 'id' ) );
        if ( isset( $profileToUpdate ) ) {
            // If trainer
            if ( $profile->isTrainer() || $profile->isCoTrainer() ) {
                // Stuff only co/trainer can edit
                $newRole = _xss( $params->get( 'role' ) );
                if ( TB_Shared_Ent_TeamData_Profile::ROLE_FAN == $newRole ||
                     TB_Shared_Ent_TeamData_Profile::ROLE_PLAYER == $newRole ||
                     TB_Shared_Ent_TeamData_Profile::ROLE_COTRAINER == $newRole ) {

                    $profileToUpdate->role = $newRole;

                }
            }
            $profileToUpdate->first_name = _xss( $params->get( 'first_name' ) );
            $profileToUpdate->last_name = _xss( $params->get( 'last_name' ) );
            $profileToUpdate->gender = _xss( $params->get( 'gender' ) );
            $profileToUpdate->player_pass_no = _xss( $params->get( 'player_pass_no' ) );
            $birthday = _xss( $params->get( 'birthday' ) );
            $profileToUpdate->birthday = empty( $birthday ) ? NULL : $birthday;
            $profileToUpdate->street = _xss( $params->get( 'street' ) );
            $profileToUpdate->zip_code = _xss( $params->get( 'zip_code' ) );
            $profileToUpdate->city = _xss( $params->get( 'city' ) );
            $profileToUpdate->phone = _xss( $params->get( 'phone' ) );
            $profileToUpdate->mobile = _xss( $params->get( 'mobile' ) );
            $profileToUpdate->misc = _xss( $params->get( 'misc' ) );
            $profileToUpdate->status = _xss( $params->get( 'status' ) );
            $profileToUpdate->save();

            // Check if profile is own - if so - return it
            if ( $profileToUpdate->id == $profile->id ) {
                $resp->addData( 'own_profile', $profileToUpdate );
            }
        } else {
            throw new Exception( 'Profile not found.', TB_Server_Core_Response::CODE_INVALID_DATA );
        }


        return $resp;
    }

    /**
     * Updates picture
     * @param TB_Server_Core_RequestData $params
     */
    public static function updatePic( TB_Server_Core_RequestData $params, $performIsOwnCheck = true ) {
        $resp = new TB_Server_Core_Response();

        // Check
        $profile = TB_Server_Core_Session::get()->getProfile();
        if ( !isset( $profile ) ) {
            throw new Exception( 'No session profile found.' );
        }

        /** @var TB_Shared_Ent_TeamData_Profile $profileToUpdate */
        $profileToUpdate = TB_Shared_Ent_TeamData_Profile::get( $params->get( 'profile_id' ) );
        if ( !isset( $profileToUpdate ) ) {
            throw new Exception( 'Invalid profile id for update pic: ' . $params->get( 'profile_id' ) );
        }

        if ( $profile->team_id != $profileToUpdate->team_id ) {
            throw new Exception( 'Both profiles needs to be in the same team.' );
        }

        if ( true == $performIsOwnCheck ) {
            if ( $profile->id != $profileToUpdate->id ) {
                throw new Exception( 'Not allowed to change pic of foreign profile.' );
            }
        }

        // Retrieve raw image data
        $slim = $params->get( 'slim' );
        if ( !isset( $slim ) ) {
            throw new Exception( 'No slim data found.' );
        }
        $slimData = json_decode( $slim, true );
        if ( !is_array( $slimData ) ) {
            throw new Exception( 'Invalid slim data.' );
        }
        $rawImgData = $slimData['output']['image'];

        // Upload to cloud
        $cloudinary = TB_Server_Utils_Cloudinary::get();

        if ( is_null( $rawImgData ) )  {

            // Delete emblem
            if ( !is_null( $profileToUpdate->pic_cloud_id ) ) {
                $res = $cloudinary->delete( $profileToUpdate->pic_cloud_id );
                if ( !is_array( $res ) || !isset( $res[ 'result' ] ) || "ok" != $res[ 'result' ] ) {
                    TB_Server_Utils_Log::get()->log( "Could not delete profile pic for id: " . $profileToUpdate->id . ' - ' . @json_encode( $res ) );
                }
            }
            $profileToUpdate->pic_url  = NULL;
            $profileToUpdate->pic_cloud_id = NULL;
            $profileToUpdate->save();

        } else {

            // Save old pic cloud id
            $oldPicCloudId = $profileToUpdate->pic_cloud_id;

            // Set new emblem
            $res = $cloudinary->upload( $rawImgData, array( 'profile', $profileToUpdate->id ) );
            if ( !is_array( $res ) || !isset( $res[ 'url' ] ) || !isset( $res[ 'public_id' ] ) ) {
                throw new Exception( 'Invalid response from Cloudinary.' );
            }
            // Update team
            $profileToUpdate->pic_url = $res[ 'url' ];
            $profileToUpdate->pic_cloud_id = $res[ 'public_id' ];
            $profileToUpdate->save();

            // If new img is saved - remove old from the cloud
            if ( !is_null( $oldPicCloudId ) ) {
                $res = $cloudinary->delete( $oldPicCloudId );
                if ( !is_array( $res ) || !isset( $res[ 'result' ] ) || "ok" != $res[ 'result' ] ) {
                    TB_Server_Utils_Log::get()->log( "Could not delete old profile pic : " . $oldPicCloudId . ' - ' . @json_encode( $res ) );
                }
            }

            // Trigger news & pn
            Francis_Core_EventHandler::get()->trigger(
                'profile_picture_updated', array(
                'profile' => $profileToUpdate
            ));

        }

        $resp->addData( 'profile', $profileToUpdate );
        return $resp;
    }

    /**
     * Update pic by trainer
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     * @throws Exception
     */
    public static function updatePicByTrainer( TB_Server_Core_RequestData $params ) {
        return self::updatePic( $params, false );
    }

    /**
     * Dummy function to be consistent with ACL
     *
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     * @throws Exception
     */
    public static function updateByTrainer( TB_Server_Core_RequestData $params ) {
        return self::update( $params );
    }

    /**
     * @param TB_Server_Core_RequestData $params
     */
    public static function addNewTeam( TB_Server_Core_RequestData $params ) {

        // Return
        $resp = new TB_Server_Core_Response();

        /** @var TB_Shared_Ent_Core_Account $account */
        $account = TB_Server_Core_Session::get()->getAccount();
        /** @var TB_Shared_Ent_TeamData_Profile $profile */
        $profile = TB_Server_Core_Session::get()->getProfile();

        $teamName = $params->get( 'team_name' );
        $teamName = TB_Shared_Utils_Validator::isValidName( $teamName ) ? $teamName : NULL;

        $teamCategory = $params->get( 'team_category' );
        $teamCategory = TB_Shared_Utils_Validator::isValidName( $teamCategory ) ? $teamCategory : NULL;


        if ( !$account->is_validated ) {
            throw new Exception( "Unvalidated account tries to create a new team." );
        }

        if ( !isset( $profile ) ) {
            throw new Exception( "No profile found." );
        }

        if ( is_null( $teamName ) ) {
            throw new Exception( "Invalid teamname." );
        }

        $dbh = TB_Shared_Db_TeamData::get();
        try {
            $dbh->beginTransaction();

            // Create team if role is TRAINER
            $team = new TB_Shared_Ent_TeamData_Team();
            $team->public_id = TB_Server_Utils_Helper::getToken( 32 );
            $team->display_name = _xss( $teamName );
            $team->category = _xss( $teamCategory );
            $team->created_ts = time();
            $team->save();
            $teamId = $team->id;

            // Duplicate trainer profile to account
            $newProfile = new TB_Shared_Ent_TeamData_Profile();
            $newProfile->team_id = $teamId;
            $newProfile->account_id = $account->id;
            $newProfile->role = TB_Shared_Ent_TeamData_Profile::ROLE_TRAINER;
            $newProfile->gender = $profile->gender;
            $newProfile->first_name = $profile->first_name;
            $newProfile->last_name = $profile->last_name;
            $newProfile->player_pass_no = $profile->player_pass_no;
            $newProfile->birthday = $profile->birthday;
            $newProfile->street = $profile->street;
            $newProfile->zip_code = $profile->zip_code;
            $newProfile->city = $profile->city;
            $newProfile->phone = $profile->phone;
            $newProfile->misc = $profile->misc;
            $newProfile->status = $profile->status;
            $newProfile->save();

            // Create profile timestamp entity
            $profileTimestamp = new TB_Shared_Ent_TeamData_ProfileTimestamp();
            $profileTimestamp->profile_id = $newProfile->id;
            $profileTimestamp->registered = time();
            $profileTimestamp->last_online = time();
            $profileTimestamp->save();

            $dbh->commit();

            $resp->addData( 'result', 'ok' );
            $resp->addData( 'new_profile_id', $newProfile->id );

        } catch ( Exception $e ) {
            $dbh->rollBack();

            $resp->addData( 'result', 'nok' );
        }

        return $resp;
    }

    /**
     * Create/update profile
     *
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     */
    public static function delete ( TB_Server_Core_RequestData $params ) {

        $resp = new TB_Server_Core_Response();
        $deletionSuccess = false;
        $emailSubject = 'Profil Löschung';
        $mailData = array();

        // Check
        /** @var TB_Shared_Ent_TeamData_Profile $currentProfile */
        $currentProfile = TB_Server_Core_Session::get()->getProfile();
        /** @var TB_Shared_Ent_TeamData_Profile $profileToDelete */
        $profileToDelete = TB_Shared_Ent_TeamData_Profile::get( $params->get( 'profile_id' ) );
        /** @var TB_Shared_Ent_TeamData_Team $teamToDelete */
        $teamToDelete = TB_Shared_Ent_TeamData_Team::get( $profileToDelete->team_id );
        $teamName = $teamToDelete->display_name;

        if ( !$currentProfile || !$profileToDelete ) {
            throw new Exception( 'Corrupt profile data.' );
        }

        if ( !$currentProfile->isTrainer() && !$currentProfile->isCoTrainer() && $currentProfile->id != $profileToDelete->id ) {
            throw new Exception( 'Not allowed to delete profile.' );
        }

        if ( $currentProfile->isCoTrainer() && $profileToDelete->isTrainer() ) {
            throw new Exception( 'Cotrainer is not allowed to delete trainer.' );
        }

        switch( $profileToDelete->role ) {

            // If profile is a normal profile - just remove the one profile
            case TB_Shared_Ent_TeamData_Profile::ROLE_COTRAINER:
            case TB_Shared_Ent_TeamData_Profile::ROLE_PLAYER:
            case TB_Shared_Ent_TeamData_Profile::ROLE_FAN:
                /** @var TB_Shared_Ent_Core_Account $accountOfProfileToDelete */
                $accountOfProfileToDelete = TB_Shared_Ent_Core_Account::get( $profileToDelete->account_id );
                array_push( $mailData, array(
                    'profile_name' => $profileToDelete->first_name . ' ' . $profileToDelete->last_name,
                    'team_name' => $teamName,
                    'subject' => $emailSubject,
                    'email' => $accountOfProfileToDelete->email
                ));
                try {
                    $profileToDelete->delete();
                    $deletionSuccess = true;
                } catch ( Exception $e ) {
                    TB_Server_Utils_Log::get()->log( $e );
                    $deletionSuccess = false;
                }
            break;

            // If profile is trainer profile - we need to remove the complete team
            case TB_Shared_Ent_TeamData_Profile::ROLE_TRAINER:
                try {  
                    $profilesToBeDeleted = TB_Shared_Ent_TeamData_Profile::getProfilesByTeamId( $teamToDelete->id );
                    /** @var TB_Shared_Ent_TeamData_Profile $ptbd */
                    foreach( $profilesToBeDeleted as $ptbd ) {
                        /** @var TB_Shared_Ent_Core_Account $accTbD */
                        $accTbD = TB_Shared_Ent_Core_Account::get( $ptbd->account_id );
                        if ( isset( $accTbD ) ) {
                            array_push( $mailData, array(
                                'profile_name' => $ptbd->first_name . ' ' . $ptbd->last_name,
                                'team_name' => $teamName,
                                'subject' => $emailSubject,
                                'email' => $accTbD->email
                            ));
                        }
                    }
                    // Note:
                    // Delete team automatically deletes all team members as their references
                    $teamToDelete->delete();

                    $deletionSuccess = true;
                } catch ( Exception $e ) {
                    TB_Server_Utils_Log::get()->log( $e );
                    $deletionSuccess = false;
                }
            break;
        }

        // Send delete confirmation mails
        if ( $deletionSuccess ) {
            foreach ( $mailData as $md ) {
                TB_Server_Utils_Mail::sendDeleteConfirmation( $md );
            }
        }

        // Return state
        $resp->addData( 'deletionsuccess', $deletionSuccess );

        return $resp;
    }

    /**
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     */
    public static function getCacheUpdate( TB_Server_Core_RequestData $params )
    {
        $resp = new TB_Server_Core_Response();

        /** @var TB_Shared_Ent_TeamData_Profile $profile */
        $profile = TB_Server_Core_Session::get()->getProfile();

        /** @var TB_Shared_Ent_TeamData_Team $team */
        $team = TB_Server_Core_Session::get()->getTeam();

        if ( $profile )
        {
            $profileTs = TB_Shared_Ent_TeamData_ProfileTimestamp::getByProfileId( $profile->id );
            $newsCount = TB_Shared_Ent_TeamData_News::getNewsCount( $profile, $profileTs );
            $resp->addData( 'newsCount', $newsCount );
            $resp->addData( 'profile_timestamp', $profileTs );
        }

        $resp->addData( 'profile',  $profile );
        $resp->addData( 'team', $team );

        return $resp;

    }

    /**
     * Dmmmy method to be consistent with ACL logic
     *
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     * @throws Exception
     */
    public static function deleteByTrainer ( TB_Server_Core_RequestData $params )
    {
        return self::delete( $params );
    }
} 