<?php
#[AllowDynamicProperties]
class PMPro_Membership_Level{

    function __construct( $id = NULL ) {
        if ( $id ) {
            return $this->get_membership_level( $id );
        } else {
            return $this->get_empty_membership_level();
        }
    }

    function __get( $key ) {
        if ( isset( $this->$key ) ) {
            $value = $this->$key;
        } else {
            $value = get_pmpro_membership_level_meta( $this->ID, $key, true );
        }
        
        return $value;
    }

    function get_empty_membership_level() {
        
        $this->ID = ''; // for backwards compatibility.
        $this->id = '';
        $this->name ='';
        $this->description = '';
        $this->confirmation = '';
        $this->initial_payment = '';
        $this->billing_amount = '';
        $this->cycle_number = '';
        $this->cycle_period = '';
        $this->billing_limit = '';
        $this->trial_amount = '';
        $this->trial_limit = '';
        $this->allow_signups = '';
        $this->expiration_number = '';
        $this->expiration_period = '';
        $this->categories = array(); // example array(1,2,4,6);

        return $this;

    }

    /**
     * Function to get the membership level object by ID.
     * @since 2.3
     */
    function get_membership_level( $id ) {

        $dblobj = $this->get_membership_level_object( $id );
        $categories = $this->get_membership_level_categories( $id );

        if ( ! empty( $dblobj ) ) {
            $this->ID = $dblobj->id;
            $this->id = $dblobj->id;
            $this->name = $dblobj->name;
            $this->description = $dblobj->description;
            $this->confirmation = $dblobj->confirmation;
            $this->initial_payment = $dblobj->initial_payment;
            $this->billing_amount = $dblobj->billing_amount;
            $this->cycle_number = $dblobj->cycle_number;
            $this->cycle_period = $dblobj->cycle_period;
            $this->billing_limit = $dblobj->billing_limit;
            $this->trial_amount = $dblobj->trial_amount;
            $this->trial_limit = $dblobj->trial_limit;
            $this->allow_signups = $dblobj->allow_signups;
            $this->expiration_number = $dblobj->expiration_number;
            $this->expiration_period = $dblobj->expiration_period;
            $this->categories = $categories;
        } else {
            return false;
        }

        return $this;
    }

    /**
     * Get a list of category ID's that belong to a membership level.
     * @since 2.3
     * @return array An array of category ID's.
     */
    function get_membership_level_categories( $id ) {
        global $wpdb;

        $dblc = $wpdb->get_results( "SELECT * FROM $wpdb->pmpro_memberships_categories WHERE membership_id = " . $id . "", ARRAY_A );

        $category_array = array();

        foreach( $dblc as $category ) {
            $category_array[] = intval( $category['category_id'] );
        }
        
        return $category_array;
    }

    /**
     * Get the object of a membership level from the database.
     * @since 2.3
     * @return object The level object.
     */
    function get_membership_level_object( $id ) {
        global $wpdb;

        // Get the discount code object.
        $dcobj = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * 
                FROM $wpdb->pmpro_membership_levels
                WHERE id = %s",
                $id
            ),
            OBJECT   
        );

        return $dcobj;
    }

    /**
     * Save or update an existing level if the level exists.
     * @since 2.3
     */
    function save() {
        global $wpdb;

        if ( empty( $this->id ) ) {
            $before_action = 'pmpro_add_membership_level';
            $after_action = 'pmpro_added_membership_level';
        } else {
            $before_action = 'pmpro_update_membership_level';
            $after_action = 'pmpro_updated_membership_level';
        }

        do_action( $before_action, $this );

        pmpro_insert_or_replace(
			$wpdb->pmpro_membership_levels,
			array(
				'id'=> $this->id,
				'name' => $this->name,
				'description' => $this->description,
				'confirmation' => $this->confirmation,
				'initial_payment' => $this->initial_payment,
				'billing_amount' => $this->billing_amount,
				'cycle_number' => $this->cycle_number,
				'cycle_period' => $this->cycle_period,
				'billing_limit' => $this->billing_limit,
				'trial_amount' => $this->trial_amount,
				'trial_limit' => $this->trial_limit,
				'expiration_number' => $this->expiration_number,
				'expiration_period' => $this->expiration_period,
				'allow_signups' => $this->allow_signups
			),
			array(
				'%d',		//id
				'%s',		//name
				'%s',		//description
				'%s',		//confirmation
				'%f',		//initial_payment
				'%f',		//billing_amount
				'%d',		//cycle_number
				'%s',		//cycle_period
				'%d',		//billing_limit
				'%f',		//trial_amount
				'%d',		//trial_limit
				'%d',		//expiration_number
				'%s',		//expiration_period
				'%d',		//allow_signups
			)
        );

        if ( $wpdb->insert_id ) {
           $this->id = $wpdb->insert_id;
        }

        // Update term restrictions if there are categories set from $this.
        if ( isset( $this->categories ) && is_array( $this->categories ) ) {
            // Only keep term IDs that still exist before linking them to this level.
            $categories = array_filter( array_map( 'intval', $this->categories ), 'term_exists' );

            pmpro_updateMembershipCategories( $this->id, $categories );
        }
        
        do_action( $after_action, $this );
    }
    /**
     * Delete a membership level and related non-historical records.
     * @since 2.3
     */
    function delete() {

        if ( empty( $this->id ) ) {
            return false;
        }

        global $wpdb;
        $r1 = false; // Remove level.
        $r2 = false; // Remove related records from level.
        $r3 = false; // Remove users from level.

        do_action( 'pmpro_delete_membership_level', $this->id );

        if ( $wpdb->delete( $wpdb->pmpro_membership_levels, array('id' => $this->id), array('%d') ) ) {
            $r1 = true;
        }

        if ( pmpro_delete_membership_level_relationships( $this->id ) ) {
            $r2 = true;
        }

        //Delete the memberships associated with this level - we're not cancelling them though
        $deleted_membership_users = $wpdb->delete(
            $wpdb->pmpro_memberships_users,
            array( 'membership_id' => $this->id ),
            array( '%d' )
        );
        
        if( $deleted_membership_users !== false ) {
            $r3 = true;
        }

        if ( $r1 == true && $r2 == true && $r3 == true ) {
            return true;
        } elseif ( $r1 == true && $r2 == false && $r3 == false ) {
            return 'Only the level was deleted. Users may still be assigned to this level and related records may remain.';
        } elseif ( $r1 == false && $r2 == true && $r3 == false ) {
            return 'Only related records were deleted. Users may still be assigned to this level.';
        } elseif( $r1 == false && $r2 == false && $r3 == true ) {
            return 'Only users were removed from this level.';
        } else {
            return false;
        }

    }

} // end of class
