<?php

/********************************************************************************
 * (c)1337 aheadware.com - All rights reserved
 ********************************************************************************/
class TB_Server_Core_Premium
{
    // Premium packages
    const PREMIUM_PACKAGE_STANDARD = 'STANDARD';
    const PREMIUM_PACKAGE_PREMIUM25 = 'PREMIUM_25';
    const PREMIUM_PACKAGE_PREMIUM50 = 'PREMIUM_50';
    const PREMIUM_PACKAGE_PREMIUM100 = 'PREMIUM_100';
    const PREMIUM_PACKAGE_PREMIUM250 = 'PREMIUM_250';
    const PREMIUM_PACKAGE_PREMIUM100_FREE = 'PREMIUM_100_FREE';

    public static $VALID_PACKAGES = array(
        self::PREMIUM_PACKAGE_STANDARD,
        self::PREMIUM_PACKAGE_PREMIUM25,
        self::PREMIUM_PACKAGE_PREMIUM50,
        self::PREMIUM_PACKAGE_PREMIUM100,
        self::PREMIUM_PACKAGE_PREMIUM100_FREE,
        self::PREMIUM_PACKAGE_PREMIUM250 => 4
    );

    public static $PACKAGE_RATING = array(
        self::PREMIUM_PACKAGE_STANDARD => 0,
        self::PREMIUM_PACKAGE_PREMIUM25 => 1,
        self::PREMIUM_PACKAGE_PREMIUM50 => 2,
        self::PREMIUM_PACKAGE_PREMIUM100 => 3,
        self::PREMIUM_PACKAGE_PREMIUM100_FREE => 3,
        self::PREMIUM_PACKAGE_PREMIUM250 => 4
    );

    // Max buddies per team
    public static $MAX_BUDDIES_PER_TEAM = array(
        self::PREMIUM_PACKAGE_STANDARD => 10,
        self::PREMIUM_PACKAGE_PREMIUM25 => 25,
        self::PREMIUM_PACKAGE_PREMIUM50 => 50,
        self::PREMIUM_PACKAGE_PREMIUM100 => 100,
        self::PREMIUM_PACKAGE_PREMIUM100_FREE => 100,
        self::PREMIUM_PACKAGE_PREMIUM250 => 350
    );

    public static $PRICES = array(
        self::PREMIUM_PACKAGE_STANDARD => 0,
        self::PREMIUM_PACKAGE_PREMIUM25 => 3.99,
        self::PREMIUM_PACKAGE_PREMIUM50 => 4.99,
        self::PREMIUM_PACKAGE_PREMIUM100 => 5.99,
        self::PREMIUM_PACKAGE_PREMIUM100_FREE => 0,
        self::PREMIUM_PACKAGE_PREMIUM250 => 9.99
    );

    public static $TAX = array(
        self::PREMIUM_PACKAGE_STANDARD => 0,
        self::PREMIUM_PACKAGE_PREMIUM25 => 0.64,
        self::PREMIUM_PACKAGE_PREMIUM50 => 0.80,
        self::PREMIUM_PACKAGE_PREMIUM100 => 0.96,
        self::PREMIUM_PACKAGE_PREMIUM100_FREE => 0,
        self::PREMIUM_PACKAGE_PREMIUM250 => 1.60
    );

    public static $BRAINTREE_PLAN_IDS = array(
        self::PREMIUM_PACKAGE_PREMIUM25 => 'PREMIUM_25',
        self::PREMIUM_PACKAGE_PREMIUM50 => 'PREMIUM_50',
        self::PREMIUM_PACKAGE_PREMIUM100 => 'PREMIUM_100'
    );

    public static $FREEMIUM_PACKAGE_IDS = array(
        self::PREMIUM_PACKAGE_PREMIUM100_FREE
    );

    public static function initBraintree()
    {
        Braintree_Configuration::environment( Francis_Utils_Config::get( 'braintree.environment' ) );
        Braintree_Configuration::merchantId( Francis_Utils_Config::get( 'braintree.merchantId' ) );
        Braintree_Configuration::publicKey( Francis_Utils_Config::get( 'braintree.publicKey' ) );
        Braintree_Configuration::privateKey( Francis_Utils_Config::get( 'braintree.privateKey' ) );
    }

    /**
     * Checks if given package id exists
     *
     * @param string $packageId
     * @return bool
     */
    public static function isValidPackageId( $packageId )
    {
        return in_array( $packageId, self::$VALID_PACKAGES );
    }

    /**
     * Checks if given id is a freemium package
     *
     * @param $packageId
     * @return bool
     */
    public static function isFreemium( $packageId )
    {
        return in_array( $packageId, self::$FREEMIUM_PACKAGE_IDS );
    }

    /**
     * Returns is given package Id is better than the current active
     *
     * @param TB_Shared_Ent_TeamData_Team $team
     * @param string $packageId
     * @return bool
     *
     * @throws Exception
     */
    public static function isPackageBetterThanCurrent( TB_Shared_Ent_TeamData_Team $team, $packageId )
    {
        if ( !in_array( $packageId, self::$VALID_PACKAGES ) )
        {
            throw new Exception( 'Invalid package id ' . $packageId );
        }

        $currentRating = self::$PACKAGE_RATING[ $team->active_premium_package ];
        $newRating = self::$PACKAGE_RATING[ $packageId ];

        return ( $newRating > $currentRating );
    }

    /**
     * @param TB_Shared_Ent_TeamData_Team $team
     * @return bool
     */
    public static function canInviteAnotherBuddy( TB_Shared_Ent_TeamData_Team $team )
    {
        $maxBuddies = self::getMaxBuddiesPerTeam( $team );
        $currentBuddies = TB_Shared_Ent_TeamData_Profile::getProfileCountByTeamId( $team->id );

        return ( $maxBuddies >= $currentBuddies );
    }

    /**
     * @param $packageId
     * @return mixed
     * @throws Exception
     */
    public static function getBraintreePlanId( $packageId )
    {
        if ( !array_key_exists( $packageId, self::$BRAINTREE_PLAN_IDS ) )
        {
            throw new Exception( 'Given packageId is not set in Braintree: ' . $packageId );
        }

        return self::$BRAINTREE_PLAN_IDS[ $packageId ];
    }

    /**
     * @param TB_Shared_Ent_TeamData_Team $team
     * @return int
     */
    public static function getMaxBuddiesPerTeam( TB_Shared_Ent_TeamData_Team $team )
    {
        if ( in_array( $team->active_premium_package, self::$MAX_BUDDIES_PER_TEAM ) )
        {
            return (int)self::$MAX_BUDDIES_PER_TEAM[ $team->active_premium_package ];
        }
        else
        {
            return 0;
        }
    }

    public static function getPackagePrice( $packageId )
    {
        if ( !self::isValidPackageId( $packageId ) )
        {
            throw new Exception( 'PREMIUM: Invalid package Id: ' . $packageId );
        }

        return self::$PRICES[ $packageId ];
    }

    public static function getPackageTax( $packageId )
    {
        if ( !self::isValidPackageId( $packageId ) )
        {
            throw new Exception( 'PREMIUM: Invalid package Id: ' . $packageId );
        }

        return self::$TAX[ $packageId ];
    }

    public static function getBraintreePlanIdByPackageId( $packageId )
    {
        $planId = NULL;

        if ( !self::isValidPackageId( $packageId ) )
        {
            throw new Exception( 'PREMIUM: Invalid package Id: ' . $packageId );
        }

        foreach( self::$BRAINTREE_PLAN_IDS as $pid => $planId )
        {
            if ( $pid === $packageId )
            {
                $planId = $pid;
                break;
            }
        }

        return $planId;
    }

    /**
     * @param TB_Shared_Ent_TeamData_Team $team
     */
    public static function createFreemiumPremiumLogEntryForTeam( TB_Shared_Ent_TeamData_Team $team )
    {
        $fromDt = new DateTime();
        $fromDt->setTime( 0, 0, 0 );

        $untilDt = DateTime::createFromFormat(
            "Y.m.d H:i:s",
            date( "Y.m.d H:i:s", strtotime( "+2 month", $fromDt->getTimestamp() ) )
        );
        $untilDt->modify( '-1 seconds' );

        $entPremiumLog = new TB_Shared_Ent_TeamData_PremiumLog();
        $entPremiumLog->team_id = $team->id;
        $entPremiumLog->package_id = TB_Server_Core_Premium::PREMIUM_PACKAGE_PREMIUM100_FREE;
        $entPremiumLog->package_price = self::getPackagePrice( TB_Server_Core_Premium::PREMIUM_PACKAGE_PREMIUM100_FREE );
        $entPremiumLog->package_tax = self::getPackageTax( TB_Server_Core_Premium::PREMIUM_PACKAGE_PREMIUM100_FREE );
        $entPremiumLog->valid_from_dt = $fromDt;
        $entPremiumLog->valid_until_dt = $untilDt;

        // Dummy values
        $entPremiumLog->account_id = 0;
        $entPremiumLog->braintree_subscription_id = '';
        $entPremiumLog->braintree_customer_id = '';
        $entPremiumLog->billing_company_name = '';
        $entPremiumLog->billing_company_tax_id = '';
        $entPremiumLog->billing_first_name = '';
        $entPremiumLog->billing_last_name = '';
        $entPremiumLog->billing_street = '';
        $entPremiumLog->billing_zip = '';
        $entPremiumLog->billing_city = '';
        $entPremiumLog->billing_country = '';
        $entPremiumLog->billing_email = '';
        $entPremiumLog->status = TB_Shared_Ent_TeamData_PremiumLog::STATUS_ACTIVE;
        $entPremiumLog->save();

    }

    /**
     * @param TB_Shared_Ent_TeamData_PremiumLog $entPremiumLog
     */
    public static function createInvoiceFromPremiumLog( TB_Shared_Ent_TeamData_PremiumLog $entPremiumLog, DateTime $periodStartDt = NULL, DateTime $periodEndDt = NULL )
    {
        $team = TB_Shared_Ent_TeamData_Team::get( $entPremiumLog->team_id );
        $teamName = '';
        if ( $team instanceof TB_Shared_Ent_TeamData_Team )
        {
            $teamName = $team->display_name;
        }
        $packageName = $entPremiumLog->package_id;

        $entInvoice = new TB_Shared_Ent_TeamData_Invoice();
        $entInvoice->ref_premium_log_id = $entPremiumLog->id;
        $entInvoice->braintree_customer_id = $entPremiumLog->braintree_customer_id;
        $entInvoice->braintree_subscription_id = $entPremiumLog->braintree_subscription_id;
        $entInvoice->account_id = $entPremiumLog->account_id;
        $entInvoice->team_id = $entPremiumLog->team_id;
        $entInvoice->team_name = $teamName;
        $entInvoice->package_id = $entPremiumLog->package_id;
        $entInvoice->package_name = $packageName;
        $entInvoice->package_price = $entPremiumLog->package_price;
        $entInvoice->package_tax = $entPremiumLog->package_tax;
        $entInvoice->billing_id = self::createBillingId( $team );
        $entInvoice->billing_date_dt = new DateTime();
        $entInvoice->billing_period_start_dt = $periodStartDt;
        $entInvoice->billing_period_end_dt = $periodEndDt;
        $entInvoice->billing_company_name = $entPremiumLog->billing_company_name;
        $entInvoice->billing_company_tax_id = $entPremiumLog->billing_company_tax_id;
        $entInvoice->billing_first_name = $entPremiumLog->billing_first_name;
        $entInvoice->billing_last_name = $entPremiumLog->billing_last_name;
        $entInvoice->billing_street = $entPremiumLog->billing_street;
        $entInvoice->billing_zip = $entPremiumLog->billing_zip;
        $entInvoice->billing_city = $entPremiumLog->billing_city;
        $entInvoice->billing_country = $entPremiumLog->billing_country;
        $entInvoice->billing_email = $entPremiumLog->billing_email;

        $entInvoice->save();

        return $entInvoice;
    }

    /**
     * Creates billing id. Structure of billing id is:
     *
     * [TEAM_ID]-[YEAR]-[MONTH]-[NO]
     *
     * @param TB_Shared_Ent_TeamData_Team $team
     */
    public static function createBillingId( TB_Shared_Ent_TeamData_Team $team )
    {

        $billingId  = $team->id;
        $billingId .= '-';
        $billingId .= date( 'Y' );
        $billingId .= '-';
        $billingId .= date( 'm' );
        $billingId .= '-';
        $billingId .= 1;

        return $billingId;
    }

    /**
     * Creates a notification for given team to inform that premium is deactivated.
     * @param TB_Shared_Ent_TeamData_Team $team
     */
    public static function notifyTeamAboutPremiumLoss( TB_Shared_Ent_TeamData_Team $team )
    {
        $newsHeader = 'Kein Premium mehr';
        $newsBody = 'Das aktuelle Premiumpaket ist abgelaufen. Ab sofort stehen euch leider keine Premium Funktionen mehr zur Verfügung.';

        /** @var TB_Shared_Ent_TeamData_News $entNews */
        $entNews = new TB_Shared_Ent_TeamData_News();
        $entNews->team_id = $team->id;
        $entNews->author_profile_id = NULL;
        $entNews->txt_key = 'txt_news_tbuddy';
        $entNews->txt_key_params_sr= array( 'news_head' => $newsHeader, 'news_body' => nl2br( $newsBody ) );
        $entNews->ref_content_type = TB_Shared_Ent_TeamData_News::REF_CONTENT_TYPE_TBUDDY_NEWS;
        $entNews->created = time();
        $entNews->save();
    }
}