<?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();

        $profile = NULL;
        $profileId = $params->get( 'profileId' );

        if ( !is_null( $profileId ) && $sessionProfile->id != $profileId )
        {
            /** @var TB_Shared_Ent_TeamData_Profile $profile */
            $profile = TB_Shared_Ent_TeamData_Profile::get( $params->get( 'profileId' ) );
            if ( is_null( $profile ) )
            {
                throw new \Exception( 'Invalid profile id.' );
            }

            if ( false === $sessionProfile->canAccessProfile( $profile ) )
            {
                throw new \Exception( 'Profile cannot be accessed by online user' );
            }
        }
        else
        {
            $profile = $sessionProfile;
        }

        $profileTeams = TB_Shared_Ent_TeamData_Team::getByProfile( $profile );
        if ( true === $params->get( 'includeTeamMembers', false ) )
        {
            $profileTeamMembers = [];
            foreach( $profileTeams as $pt )
            {
                $profileTeamMembers[ $pt->id ] = array();
                $members = TB_Shared_Ent_TeamData_Profile::getProfilesByTeamId( $pt->id );
                /** @var TB_Shared_Ent_TeamData_Profile $member */
                foreach( $members as $member )
                {
                    array_push( $profileTeamMembers[ $pt->id ], $member->asArray() );
                }
            }

            $resp->addData( 'profile_team_members', $profileTeamMembers );
        }

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

        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();

        $birthdayDt = NULL;
        $birthday = $params->get( 'birthday' );
        if ( $birthday )
        {
            $birthdayDt = DateTime::createFromFormat( 'Y-m-d', $birthday );
            $birthdayDt->setTime( 0, 0, 0 );
            $birthdayDt->add( new DateInterval( 'PT6H' ) );
        }

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

        $profileToUpdate->status = _xss( $params->get( 'status' ) );
        $profileToUpdate->first_name = _xss( $params->get( 'firstName' ) );
        $profileToUpdate->last_name = _xss( $params->get( 'lastName' ) );
        $profileToUpdate->birthday_dt = $birthdayDt;
        $profileToUpdate->touch( 'birthday_dt' );
        //$profileToUpdate->misc = _xss( $params->get( 'misc' ) );

        $teamProps = $params->get( 'teamProps' );
        if ( $teamProps )
        {
            $profileToUpdate->team_prop_js = $teamProps;
        }

        $profileToUpdate->save();

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

        return $resp;
    }

    public static function updateProfileAddress( TB_Server_Core_RequestData $params )
    {
        $resp = new TB_Server_Core_Response();

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

        $profileToUpdate->street = _xss( $params->get( 'street' ) );
        $profileToUpdate->zip_code = _xss( $params->get( 'zipCode' ) );
        $profileToUpdate->city = _xss( $params->get( 'city' ) );
        $profileToUpdate->country = _xss( $params->get( 'country' ) );
        $profileToUpdate->phone = _xss( $params->get( 'phone' ) );
        $profileToUpdate->mobile = _xss( $params->get( 'mobile' ) );

        $profileToUpdate->save();

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

        return $resp;

    }

    public static function grantManagerAccess( 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();

        $team = TB_Shared_Ent_TeamData_Team::get( $params->get( 'teamId' ) );

        if ( !$team )
        {
            throw new \Exception( 'Invalid team' );
        }

        $resp->addData( 'managerIds', $sessionProfile->manager_access_ids_js );

        if ( false === $sessionProfile->isManagerAccessAllowed( $team->id ) )
        {
            throw new \Exception( 'Not allowed to perform manager actions.' );
        }

        $profile = TB_Shared_Ent_TeamData_Profile::get( $params->get('profileId') );
        if ( !$profile )
        {
            throw new \Exception( 'Invalid profile' );
        }

        if ( false === $profile->isInTeam( $team->id ) )
        {
            throw new \Exception( 'Profile is not in team.' );
        }

        if ( false === $profile->isAdminOfTeam( $team->id ) )
        {
            throw new \Exception( 'Profile must be admin of team' );
        }

        $accessIds = $profile->manager_access_ids_js;
        if ( !is_array( $accessIds ) )
        {
            $accessIds = array();
        }

        if ( !in_array( $team->id, $accessIds ) )
        {
            array_push( $accessIds, +$team->id );
            $profile->manager_access_ids_js = $accessIds;
            $profile->save();
        }

        return $resp;
    }

    public static function removeManagerAccess(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();

        $team = TB_Shared_Ent_TeamData_Team::get( $params->get( 'teamId' ) );

        if ( !$team )
        {
            throw new \Exception( 'Invalid team' );
        }

        if ( false === $sessionProfile->isManagerAccessAllowed( $team->id ) )
        {
            throw new \Exception( 'Not allowed to perform manager actions.' );
        }

        $profile = TB_Shared_Ent_TeamData_Profile::get( $params->get('profileId') );
        if ( !$profile )
        {
            throw new \Exception( 'Invalid profile' );
        }

        if ( false === $profile->isInTeam( $team->id ) )
        {
            throw new \Exception( 'Profile is not in team.' );
        }

        if ( false === $profile->isAdminOfTeam( $team->id ) )
        {
            throw new \Exception( 'Profile must be admin of team' );
        }

        $accessIds = $profile->manager_access_ids_js;
        if ( !is_array( $accessIds ) )
        {
            $accessIds = array();
        }

        if ( in_array( $team->id, $accessIds ) )
        {
            $accessIds = array_diff( $accessIds, array( +$team->id ) );
            $profile->manager_access_ids_js = $accessIds;
            $profile->save();
        }

        return $resp;
    }

    public static function updatePrivacy( TB_Server_Core_RequestData $params )
    {
        $resp = new TB_Server_Core_Response();

        $teamData = $params->get( 'teamData' );

        $sessionProfile = TB_Server_Core_Session::get()->getProfile();

        if ( $teamData && is_array( $teamData ) )
        {
            foreach ( $teamData as $td )
            {
                if ( $sessionProfile->isInTeam( $td[ 'teamId' ] ) )
                {
                    $sessionProfile->setAnonymousStateInTeam( $td[ 'teamId' ], $td[ 'isAnonymous' ] );
                }
            }

            $sessionProfile->save();
        }

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

        return $resp;
    }

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

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

        $rawImgData = $params->get( 'imageData' );

        // 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[ 'secure_url' ] ) || !isset( $res[ 'public_id' ] ) ) {
                throw new Exception( 'Invalid response from Cloudinary.' );
            }
            // Update team
            $profileToUpdate->pic_url = $res[ 'secure_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 ) );
                }
            }

        }

        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 );
    }
} 