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


class TB_Server_Control_Stats {

    /**
     * @param TB_Server_Core_RequestData $params
     * @return TB_Server_Core_Response
     */
    static public function dashboard( TB_Server_Core_RequestData $params ) {

        $resp = new TB_Server_Core_Response();

        $profile = TB_Server_Core_Session::get()->getProfile();
        $team = TB_Server_Core_Session::get()->getTeam();

        // Stats data
        $yesterday = self::getLatestDateString();
        $compareDate = self::getCompareDateString( $yesterday );
        $playerRank = self::getPlayerRank( $profile->id, $yesterday );
        $ranksTotal = self::getPlayerRankTotal( $profile->team_id, $yesterday );
        $playerRankCompare = self::getPlayerRank( $profile->id, $compareDate );
        $playerReliability = self::getPlayerReliability( $profile, $yesterday );
        $playerAttendeeReliability = self::getPlayerReliabilityAttendee( $profile, $yesterday );
        $teamAppointmentReactions = self::getTeamAppointmentReactions( $profile->team_id );
        $teamReliability = self::getTeamReliability( $profile->team_id, $yesterday );
        $teamAttendeeReliability = self::getTeamReliabilityAttendee( $profile->team_id, $yesterday );
        $generalAppointmentReactions = self::getGeneralAppointmentReactions();
        $generalReliability = self::getGeneralReliability( $yesterday );
        $generalAttendeeReliability = self::getGeneralReliabilityAttendee( $yesterday );
        $teamRanking = self::getTeamRanking( $profile->team_id, $yesterday );

        $newStats = array(
            'playerRank' => $playerRank,
            'ranksTotal' => $ranksTotal,
            'playerRankCompare' => $playerRankCompare,
            'playerReliability' => $playerReliability,
            'playerAttendeeReliability' => $playerAttendeeReliability,
            'teamAppointmentReactions' => $teamAppointmentReactions,
            'teamReliability' => $teamReliability,
            'teamAttendeeReliability' => $teamAttendeeReliability,
            'generalAppointmentReactions' => $generalAppointmentReactions,
            'generalReliability' => $generalReliability,
            'generalAttendeeReliability' => $generalAttendeeReliability,
            'teamRanking' => $teamRanking
         );

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

        return $resp;

    }

    /**
     * @param $date
     */
    static protected function getCompareDateString( $date )
    {
        return date( 'Y-m-d', strtotime( $date ) - 7 * 60 * 60 * 24 );
    }

    /**
     *
     * @return false|string
     */
    static protected function getLatestDateString()
    {
        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT MAX(entry_dt) AS `max_date` FROM `stat_user`';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute();
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) || isset( $row[ 'max_date' ] ) ) {
            return date( 'Y-m-d', strtotime( $row[ 'max_date' ] ) );
        } else {
            // Yesterday
            return date( 'Y-m-d', time() - 60 * 60 * 24 );
        }
    }

    /**
     * Get rank of player of specific date
     *
     * @param int $profileId
     * @param string $date 'YYYY-MM-DD'
     * @return null | int
     */
    static protected function getPlayerRank( $profileId, $date ) {

        $rank = NULL;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = "CALL proc_getRanking ( :profile_id, :when, @returnInt );SELECT @returnInt;";
        $stmt = $dbh->prepare( $sql );
        $stmt->bindParam( ':profile_id', $profileId, PDO::PARAM_INT );
        $stmt->bindParam( ':when', $date, PDO::PARAM_STR );
        $stmt->execute();
        $stmt->closeCursor();
        $row = $dbh->query( "SELECT @returnInt AS rank" )->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $rank = ( $row !== false ) ? $row[ 'rank' ] : NULL;
        }

        return $rank;
    }

    /**
     * Get total amount of ranks
     * @param int $teamId
     * @param string $date 'YYYY-MM-DD'
     */
    static protected function getPlayerRankTotal( $teamId, $date ) {
        $total = NULL;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT COUNT(*) AS totalRanks FROM `stat_user` WHERE b_team_id = :team_id AND entry_dt = :when';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $teamId, ':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $total = $row[ 'totalRanks' ];
        }

        return $total;
    }

    /**
     * Get player reliability in percentage
     *
     * @param TB_Shared_Ent_TeamData_Profile $profile
     * @param $date
     * @return null | float
     */
    static protected function getPlayerReliability( TB_Shared_Ent_TeamData_Profile $profile, $date ) {
        $reliability = NULL;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT tReagiert/tGesamt AS reliability FROM `stat_user` WHERE b_team_id = :team_id AND b_spieler_id = :profile_id AND entry_dt = :when';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $profile->team_id, ':profile_id' => $profile->id, ':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reliability = $row[ 'reliability' ];
        }

        return $reliability;
    }

    /**
     * Get players reliability for attendance of appointments
     *
     * @param TB_Shared_Ent_TeamData_Profile $profile
     * @param $date
     * @return null | float
     */
    static protected function getPlayerReliabilityAttendee( TB_Shared_Ent_TeamData_Profile $profile, $date ) {
        $reliabilityAttendee = NULL;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT tZusage/tReagiert AS reliabilityAttendee FROM `stat_user` WHERE b_team_id = :team_id AND b_spieler_id = :profile_id AND entry_dt = :when';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $profile->team_id, ':profile_id' => $profile->id, ':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reliabilityAttendee = $row[ 'reliabilityAttendee' ];
        }

        return $reliabilityAttendee;
    }

    /**
     * Get amount of appointment reactions for given team id
     * @param int $teamId
     * @return int
     */
    static protected function getTeamAppointmentReactions( $teamId ) {
        $reactions = 0;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT COUNT(*) AS numReaction FROM appointment t INNER JOIN attendee a ON (t.id = a.appointment_id) WHERE t.team_id = :team_id AND FROM_UNIXTIME(t.starttime)<=DATE_ADD(CURDATE(), INTERVAL 14 DAY)';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $teamId ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reactions = $row[ 'numReaction' ];
        }

        return $reactions;
    }

    /**
     * Get amount of appointment reactions
     * @return int
     */
    static protected function getGeneralAppointmentReactions() {
        $reactions = 0;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT COUNT(*) AS numReaction FROM appointment t INNER JOIN attendee a ON (t.id = a.appointment_id) WHERE FROM_UNIXTIME(t.starttime)<=DATE_ADD(CURDATE(), INTERVAL 14 DAY)';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute();
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reactions = $row[ 'numReaction' ];
        }

        return $reactions;
    }

    /**
     * Get average team reliability
     * @param int $teamId
     * @param string $date 'YYYY-MM-DD'
     * @return float
     */
    static protected function getTeamReliability( $teamId, $date ) {
        $reliability = 0;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT AVG(tReagiert/tGesamt) AS avgVerlaessl FROM `stat_user` WHERE entry_dt = :when AND b_team_id = :team_id';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $teamId, ':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reliability = $row[ 'avgVerlaessl' ];
        }

        return $reliability;
    }

    /**
     * Get average reliability in general
     * @param string $date 'YYYY-MM-DD'
     * @return float
     */
    static protected function getGeneralReliability( $date ) {
        $reliability = 0;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT AVG(tReagiert/tGesamt) AS avgVerlaessl FROM `stat_user` WHERE entry_dt = :when';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( ':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reliability = $row[ 'avgVerlaessl' ];
        }

        return $reliability;
    }

    /**
     * Get reliability for attendance of given team
     * @param int $teamId
     * @param string $date 'YYYY-MM-DD'
     * @return float
     */
    static protected function getTeamReliabilityAttendee( $teamId, $date ) {

        $reliabilityAttendee = 0;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT AVG(tZusage/tReagiert) AS avgZusagen FROM `stat_user` WHERE entry_dt = :when AND b_team_id = :team_id';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $teamId, ':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reliabilityAttendee = $row[ 'avgZusagen' ];
        }

        return $reliabilityAttendee;

    }

    /**
     * Get reliability for attendance in general
     * @param string $date 'YYYY-MM-DD'
     * @return float
     */
    static protected function getGeneralReliabilityAttendee( $date ) {

        $reliabilityAttendee = 0;

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'SELECT AVG(tZusage/tReagiert) AS avgZusagen FROM `stat_user` WHERE entry_dt = :when';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array(':when' => $date ) );
        $row = $stmt->fetch( PDO::FETCH_ASSOC );
        if ( isset( $row ) ) {
            $reliabilityAttendee = $row[ 'avgZusagen' ];
        }

        return $reliabilityAttendee;

    }

    /**
     * Get overall team ranking
     * @param int $teamId
     * @param string $date 'YYYY-MM-DD'
     * @return array
     */
    static protected function getTeamRanking( $teamId, $date ) {

        $teamRanking = array();

        $dbh = TB_Shared_Db_TeamData::get();
        $sql = 'select rank, b_spielerName, b_spieler_id, ReaktQuote, ZuQuote, AbQuote,
NoReaction from
(select b_spielerName, b_spieler_ID, tReagiert/tGesamt as
ReaktQuote, tZusage/tReagiert as ZuQuote, tAbsage/tReagiert as
AbQuote, tKeineReaktion/tGesamt as NoReaction,
 @prev := @curr,
 @curr := (tReagiert/tGesamt)+(tZusage/tReagiert),
 @rank1:= @rank1+1,
 @rank := IF(@prev = @curr, @rank, @rank1) as rank
 from stat_user, 
 (SELECT @curr := null, @prev := null, @rank1 := 0, @rank := 0) sel1
 where b_team_id = :team_id and entry_dt =
:when order by ReaktQuote desc, ZuQuote desc ) as tab';

        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $teamId, ':when' => $date ) );
        $rows = $stmt->fetchAll( PDO::FETCH_ASSOC );
        if ( isset( $rows ) ) {
            $teamRanking = $rows;
        }

        return $teamRanking;
    }


    /**
     * @param $teamId
     */
    static protected function getPlayerReliabilityRanking( $teamId ) {
        $sql = "select distinct concat(p.first_name, ' ',p.last_name) AS fullname,
            (select count(app.id)
            from appointment app
            where app.team_id = :team_id and FROM_UNIXTIME(app.starttime)>'2015-01-01') as Gesamt,
            count(*) as Counter,
            count(*)/(select count(app.id)
            from appointment app
            where app.team_id = :team_id and FROM_UNIXTIME(app.starttime)>'2015-01-01') as Anteil,
            (select
            count(*) as Counter
            from appointment t1
            inner join attendee a1 on (t1.id = a1.appointment_id)
            inner join profile p1 on (a1.profile_id = p1.id)
            where t1.team_id = :team_id and FROM_UNIXTIME(t1.starttime)>'2015-01-01'
            and a1.`status` = 'accepted' and a1.profile_id = p.id) as Zusage,
            (select
            count(*) as Counter
            from appointment t1
            inner join attendee a1 on (t1.id = a1.appointment_id)
            inner join profile p1 on (a1.profile_id = p1.id)
            where t1.team_id = :team_id and FROM_UNIXTIME(t1.starttime)>'2015-01-01'
            and a1.`status` = 'declined' and a1.profile_id = p.id) as Absage
            from appointment t
            inner join attendee a on (t.id = a.appointment_id)
            inner join profile p on (a.profile_id = p.id)
            where t.team_id = :team_id and FROM_UNIXTIME(t.starttime)>'2015-01-01'
            group by p.first_name,p.last_name
            order by Counter desc, Zusage desc";

        $dbh = TB_Shared_Db_TeamData::get();
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array( 'team_id' => $teamId ) );
        $res = $stmt->fetchAll( PDO::FETCH_ASSOC );

        return $res;
    }
}