<?php

/**
 * Handles create/update operations.
 *
 * @author     Time.ly Network Inc.
 * @since      2.0
 *
 * @package    AI1EC
 * @subpackage AI1EC.Model
 */
class Ai1ec_Event_Creating extends Ai1ec_Base {

    protected function is_valid_event( $post ) {
            // verify this came from the our screen and with proper authorization,
        // because save_post can be triggered at other times
        if (
            ! isset( $_POST[AI1EC_POST_TYPE] ) ||
            ! wp_verify_nonce( $_POST[AI1EC_POST_TYPE], 'ai1ec' )
        ) {
            return false;
        }

        if (
            isset( $post->post_status ) &&
            'auto-draft' === $post->post_status
        ) {
            return false;
        }

        // verify if this is not inline-editing
        if (
            isset( $_REQUEST['action'] ) &&
            'inline-save' === $_REQUEST['action']
        ) {
            return false;
        }

        // verify that the post_type is that of an event
        if ( $post->post_type !==  AI1EC_POST_TYPE ) {
            return false;
        }

        return true;
    }

    private function _parse_post_to_event( $post_id ) {

        /**
         * =====================================================================
         *
         * CHANGE CODE BELOW TO HAVE FOLLOWING PROPERTIES:
         * - be initializiable from model;
         * - have sane defaults;
         * - avoid that cluster of isset and ternary operator.
         *
         * =====================================================================
         */

        $all_day          = isset( $_POST['ai1ec_all_day_event'] )    ? 1                                                                 : 0;
        $instant_event    = isset( $_POST['ai1ec_instant_event'] )    ? 1                                                                 : 0;
        $timezone_name    = isset( $_POST['ai1ec_timezone_name'] )    ? sanitize_text_field( $_POST['ai1ec_timezone_name'] )              : 'sys.default';
        $start_time       = isset( $_POST['ai1ec_start_time'] )       ? sanitize_text_field( $_POST['ai1ec_start_time'] )                 : '';
        $end_time         = isset( $_POST['ai1ec_end_time'] )         ? sanitize_text_field( $_POST['ai1ec_end_time'] )                   : '';
        $venue            = isset( $_POST['ai1ec_venue'] )            ? sanitize_text_field( $_POST['ai1ec_venue'] )                      : '';
        $address          = isset( $_POST['ai1ec_address'] )          ? sanitize_text_field( $_POST['ai1ec_address'] )                    : '';
        $city             = isset( $_POST['ai1ec_city'] )             ? sanitize_text_field( $_POST['ai1ec_city'] )                       : '';
        $province         = isset( $_POST['ai1ec_province'] )         ? sanitize_text_field( $_POST['ai1ec_province'] )                   : '';
        $postal_code      = isset( $_POST['ai1ec_postal_code'] )      ? sanitize_text_field( $_POST['ai1ec_postal_code'] )                : '';
        $country          = isset( $_POST['ai1ec_country'] )          ? sanitize_text_field( $_POST['ai1ec_country'] )                    : '';
        $google_map       = isset( $_POST['ai1ec_google_map'] )       ? 1                                                                 : 0;
        $cost             = isset( $_POST['ai1ec_cost'] )             ? sanitize_text_field( $_POST['ai1ec_cost'] )                       : '';
        $is_free          = isset( $_POST['ai1ec_is_free'] )          ? (bool)$_POST['ai1ec_is_free']                                     : false;
        $ticket_url       = isset( $_POST['ai1ec_ticket_url'] )       ? sanitize_text_field( $_POST['ai1ec_ticket_url'] )                 : '';
        $contact_name     = isset( $_POST['ai1ec_contact_name'] )     ? sanitize_text_field( $_POST['ai1ec_contact_name'] )               : '';
        $contact_phone    = isset( $_POST['ai1ec_contact_phone'] )    ? sanitize_text_field( $_POST['ai1ec_contact_phone'] )              : '';
        $contact_email    = isset( $_POST['ai1ec_contact_email'] )    ? sanitize_text_field( $_POST['ai1ec_contact_email'] )              : '';
        $contact_url      = isset( $_POST['ai1ec_contact_url'] )      ? sanitize_text_field( $_POST['ai1ec_contact_url'] )                : '';
        $show_coordinates = isset( $_POST['ai1ec_input_coordinates'] )? 1                                                                 : 0;
        $longitude        = isset( $_POST['ai1ec_longitude'] )        ? sanitize_text_field( $_POST['ai1ec_longitude'] )                  : '';
        $latitude         = isset( $_POST['ai1ec_latitude'] )         ? sanitize_text_field( $_POST['ai1ec_latitude'] )                   : '';
        $cost_type        = isset( $_POST['ai1ec_cost_type'] )        ? sanitize_text_field( $_POST['ai1ec_cost_type'] )                  : '';
        $rrule            = null;
        $exrule           = null;
        $exdate           = null;
        $rdate            = null;

        if ( 'external' !== $cost_type ) {
            $ticket_url = '';
        }

        $this->_remap_recurrence_dates();
        // if rrule is set, convert it from local to UTC time
        if (
            isset( $_POST['ai1ec_repeat'] ) &&
            ! empty( $_POST['ai1ec_repeat'] )
        ) {
            $rrule = $_POST['ai1ec_rrule'];
        }

        // add manual dates
        if (
            isset( $_POST['ai1ec_exdate'] ) &&
            ! empty( $_POST['ai1ec_exdate'] )
        ) {
            $exdate = $_POST['ai1ec_exdate'];
        }
        if (
            isset( $_POST['ai1ec_rdate'] ) &&
            ! empty( $_POST['ai1ec_rdate'] )
        ) {
            $rdate = $_POST['ai1ec_rdate'];
        }

        // if exrule is set, convert it from local to UTC time
        if (
            isset( $_POST['ai1ec_exclude'] ) &&
            ! empty( $_POST['ai1ec_exclude'] ) &&
            ( null !== $rrule || null !== $rdate ) // no point for exclusion, if repetition is not set
        ) {
            $exrule = $this->_registry->get( 'recurrence.rule' )->merge_exrule(
                $_POST['ai1ec_exrule'],
                $rrule
            );
        }

        $is_new = false;
        try {
            $event =  $this->_registry->get(
                'model.event',
                $post_id ? $post_id : null
            );
        } catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
            // Post exists, but event data hasn't been saved yet. Create new event
            // object.
            $is_new = true;
            $event  =  $this->_registry->get( 'model.event' );
        }
        $formatted_timezone = $this->_registry->get( 'date.timezone' )
                ->get_name( $timezone_name );
        if ( empty( $timezone_name ) || ! $formatted_timezone ) {
            $timezone_name = 'sys.default';
        }

        unset( $formatted_timezone );
        $start_time_entry = $this->_registry
            ->get( 'date.time', $start_time, $timezone_name );
        $end_time_entry   = $this->_registry
            ->get( 'date.time', $end_time,   $timezone_name );

        $timezone_name = $start_time_entry->get_timezone();
        if ( null === $timezone_name ) {
            $timezone_name = $start_time_entry->get_default_format_timezone();
        }

        $event->set( 'post_id',          $post_id );
        $event->set( 'start',            $start_time_entry );
        if ( $instant_event ) {
            $event->set_no_end_time();
        } else {
            $event->set( 'end',           $end_time_entry );
            $event->set( 'instant_event', false );
        }
        $event->set( 'timezone_name',    $timezone_name );
        $event->set( 'allday',           $all_day );
        $event->set( 'venue',            $venue );
        $event->set( 'address',          $address );
        $event->set( 'city',             $city );
        $event->set( 'province',         $province );
        $event->set( 'postal_code',      $postal_code );
        $event->set( 'country',          $country );
        $event->set( 'show_map',         $google_map );
        $event->set( 'cost',             $cost );
        $event->set( 'is_free',          $is_free );
        $event->set( 'ticket_url',       $ticket_url );
        $event->set( 'contact_name',     $contact_name );
        $event->set( 'contact_phone',    $contact_phone );
        $event->set( 'contact_email',    $contact_email );
        $event->set( 'contact_url',      $contact_url );
        $event->set( 'recurrence_rules', $rrule );
        $event->set( 'exception_rules',  $exrule );
        $event->set( 'exception_dates',  $exdate );
        $event->set( 'recurrence_dates', $rdate );
        $event->set( 'show_coordinates', $show_coordinates );
        $event->set( 'longitude',        trim( $longitude ) );
        $event->set( 'latitude',         trim( $latitude ) );
        $event->set( 'ical_uid',         $event->get_uid() );

        return array(
            'event'        => $event,
            'is_new'       => $is_new
        );
    }

    /**
     * Saves meta post data.
     *
     * @wp_hook save_post
     *
     * @param  int    $post_id Post ID.
     * @param  object $post    Post object.
     * @param  update
     *
     * @return object|null Saved Ai1ec_Event object if successful or null.
     */
    public function save_post( $post_id, $post, $update ) {

        if ( false === $this->is_valid_event( $post ) ) {
            return null;
        }

        // LABEL:magicquotes
        // remove WordPress `magical` slashes - we work around it ourselves
        $_POST = stripslashes_deep( $_POST );

        $data = $this->_parse_post_to_event( $post_id );
        if ( ! $data ) {
            return null;
        }
        $event        = $data['event'];
        $is_new       = $data['is_new'];

        $banner_image = isset( $_POST['ai1ec_banner_image'] )     ? sanitize_text_field( $_POST['ai1ec_banner_image'] ) : '';
        $cost_type    = isset( $_POST['ai1ec_cost_type'] )        ? sanitize_text_field( $_POST['ai1ec_cost_type'] )    : '';

        update_post_meta( $post_id, 'ai1ec_banner_image', $banner_image );
        if ( $cost_type ) {
            update_post_meta( $post_id, '_ai1ec_cost_type', $cost_type );
        }
        $api = $this->_registry->get( 'model.api.api-ticketing' );
        if ( $update === false ) {
            //this method just creates the API event, the update action
            //is treated by another hook (pre_update_event inside api )
            if ( 'tickets' === $cost_type ) {
                $result = $api->store_event( $event, $post, false );
                if ( true !== $result ) {
                    $_POST['_ticket_store_event_error'] = $result;
                } else {
                    update_post_meta(
                        $post_id,
                        '_ai1ec_timely_tickets_url',
                        $api->get_api_event_buy_ticket_url( $event->get( 'post_id' ) )
                    );
                }
            }
        }
        if ( 'tickets' === $cost_type ) {
            update_post_meta(
                $post_id,
                '_ai1ec_timely_tickets_url',
                $api->get_api_event_buy_ticket_url( $event->get( 'post_id' ) )
            );
        } else {
            delete_post_meta(
                $post_id,
                '_ai1ec_timely_tickets_url'
            );
        }

        // let other extensions save their fields.
        do_action( 'ai1ec_save_post', $event );

        $event->save( ! $is_new );

        // LABEL:magicquotes
        // restore `magic` WordPress quotes to maintain compatibility
        $_POST = add_magic_quotes( $_POST );

        $api = $this->_registry->get( 'model.api.api-registration' );
        $api->check_settings();

        return $event;
    }

    private function get_sendback_page( $post_id ) {
        $sendback  = wp_get_referer();
        $page_base = Ai1ec_Wp_Uri_Helper::get_pagebase( $sendback ); //$_SERVER['REQUEST_URI'] );
        if ( 'post.php' === $page_base ) {
            return get_edit_post_link( $post_id, 'url' );
        } else {
            return admin_url( 'edit.php?post_type=ai1ec_event' );
        }
    }

    /**
     * Handle PRE (ticket event) update.
     * Just handle the Ticket Events, other kind of post are ignored
     * @wp_hook pre_post_update
     *
     */
    public function pre_post_update ( $post_id, $new_post_data ) {

        // LABEL:magicquotes
        // remove WordPress `magical` slashes - we work around it ourselves
        $_POST = stripslashes_deep( $_POST );

        $api    = $this->_registry->get( 'model.api.api-ticketing' );
        $action = $this->current_action();
        switch( $action ) {
        case 'inline-save': //quick edit from edit page
            $fields = array();
            if ( false === ai1ec_is_blank( $_REQUEST['post_title'] ) ) {
                $fields['title'] = sanitize_text_field( $_REQUEST['post_title'] );
            }
            if ( false === ai1ec_is_blank( $_REQUEST['_status'] ) ) {
                $fields['status'] = $_REQUEST['_status'];
            }
            if ( isset( $_REQUEST['keep_private'] ) && 'private' === $_REQUEST['keep_private'] ) {
                $fields['visibility'] = 'private';
            } else if ( isset( $_REQUEST['post_password'] ) && false === ai1ec_is_blank( $_REQUEST['post_password'] ) ) {
                $fields['visibility'] = 'password';
            }
            if ( 0 < count( $fields ) ) {
                $post    = get_post( $post_id );
                $ajax    = defined( 'DOING_AJAX' ) && DOING_AJAX;
                $message = $api->update_api_event_fields( $post, $fields, 'update', $ajax );
                if ( null !== $message )  {
                    if ( $ajax ) {
                        wp_die( $message );
                    } else {
                        wp_redirect( $this->get_sendback_page( $post_id ) );
                        exit();
                    }
                }
            }
            return;
        case 'edit': //bulk edition from edit page
            $fields          = array();
            if ( false === ai1ec_is_blank( $_REQUEST['_status'] ) ) {
                $fields['status'] = $_REQUEST['_status'];
            }
            if ( 0 < count( $fields ) ) {
                $post    = get_post( $post_id );
                $ajax    = defined( 'DOING_AJAX' ) && DOING_AJAX;
                $message = $api->update_api_event_fields( $post, $fields, 'update', $ajax );
                if ( null !== $message )  {
                    if ( $ajax ) {
                        wp_die( $message );
                    } else {
                        wp_redirect( $this->get_sendback_page( $post_id ) );
                        exit();
                    }
                }
            }
            return;
        case 'editpost': //edition from post page
            $new_post_data['ID'] = $post_id;
            $post = new WP_Post( (object) $new_post_data );
            if ( false === $this->is_valid_event( $post ) ) {
                break;
            }
            $data  = $this->_parse_post_to_event( $post_id );
            if ( ! $data ) {
                break;
            }
            $event     = $data['event'];
            $cost_type = isset( $_REQUEST['ai1ec_cost_type'] ) ? $_REQUEST['ai1ec_cost_type'] : '';
            if ( 'tickets' === $cost_type ) {
                $result = $api->store_event( $event, $post, true );
                if ( true !== $result ) {
                    wp_redirect( $this->get_sendback_page( $post_id ) );
                    exit();
                }
            } else {
                $message = $api->delete_api_event( $post_id, 'update', false );
                if ( null !== $message )  {
                    wp_redirect( $this->get_sendback_page( $post_id ) );
                    exit();
                }
            }
            break;
        default:
            break;
        }

        // LABEL:magicquotes
        // restore `magic` WordPress quotes to maintain compatibility
        $_POST = add_magic_quotes( $_POST );
    }

    protected function current_action() {
        $action = '';
        if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
            $action = 'delete';
        } else {
            if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) {
                $action = $_REQUEST['action'];
            }
            if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) {
                $action = $_REQUEST['action2'];
            }
        }
        return $action;
    }

    /**
     * _create_duplicate_post method
     *
     * Create copy of event by calling {@uses wp_insert_post} function.
     * Using 'post_parent' to add hierarchy.
     *
     * @param array $data Event instance data to copy
     *
     * @return int|bool New post ID or false on failure
     **/
    public function create_duplicate_post() {
        if ( ! isset( $_POST['post_ID'] ) ) {
            return false;
        }
        $clean_fields = array(
            'ai1ec_repeat'      => NULL,
            'ai1ec_rrule'       => '',
            'ai1ec_exrule'      => '',
            'ai1ec_exdate'      => '',
            'post_ID'           => NULL,
            'post_name'         => NULL,
            'ai1ec_instance_id' => NULL,
        );
        $old_post_id = $_POST['post_ID'];
        $instance_id = $_POST['ai1ec_instance_id'];
        foreach ( $clean_fields as $field => $to_value ) {
            if ( NULL === $to_value ) {
                unset( $_POST[$field] );
            } else {
                $_POST[$field] = $to_value;
            }
        }
        $_POST                   = _wp_translate_postdata( false, $_POST );
        $_POST['post_parent']    = $old_post_id;
        if ( isset( $_POST['post_title'] ) ) {
            $_POST['post_title'] = sanitize_text_field( $_POST['post_title'] );
        }
        $post_id = wp_insert_post( $_POST );
        $this->_registry->get( 'model.event.parent' )->event_parent(
            $post_id,
            $old_post_id,
            $instance_id
        );
        return $post_id;
    }

    /**
     * Cleans calendar shortcodes from event content.
     *
     * @param array $data    An array of slashed post data.
     * @param array $postarr An array of sanitized, but otherwise unmodified post data.
     *
     * @return array An array of slashed post data.
     */
    public function wp_insert_post_data( $data ) {
        global $shortcode_tags;
        if (
            ! isset( $data['post_type'] ) ||
            ! isset( $data['post_content'] ) ||
            AI1EC_POST_TYPE !== $data['post_type'] ||
            empty( $shortcode_tags ) ||
            ! is_array( $shortcode_tags ) ||
            false === strpos( $data['post_content'], '[' )
        ) {
            return $data;
        }
        $pattern              = get_shortcode_regex();
        $data['post_content'] = preg_replace_callback(
            "/$pattern/s",
            array( $this, 'strip_shortcode_tag' ),
            $data['post_content']
        );
        return $data;
    }

    /**
     * Reutrns shortcode or stripped content for given shortcode.
     * Currently regex callback function passes as $tag argument 7-element long
     * array.
     * First element ($tag[0]) is not modified full shortcode text.
     * Third element ($tag[2]) is pure shortcode identifier.
     * Sixth element ($tag[5]) contains shortcode content if any
     * [ai1ec_test]content[/ai1ec].
     *
     * @param array $tag Incoming data.
     *
     * @return string Shortcode replace tag.
     */
    public function strip_shortcode_tag( $tag ) {
        if (
            count( $tag ) < 7 ||
            'ai1ec' !== substr( $tag[2], 0, 5 ) ||
            ! apply_filters( 'ai1ec_content_remove_shortcode_' . $tag[2], false )
        ) {
            return $tag[0];
        }
        return $tag[5];
    }

    protected function _remap_recurrence_dates() {
        if (
            isset( $_POST['ai1ec_exclude'] ) &&
            'EXDATE' === substr( $_POST['ai1ec_exrule'], 0, 6 )
        ) {
            $_POST['ai1ec_exdate'] = substr( $_POST['ai1ec_exrule'], 7 );
            unset( $_POST['ai1ec_exclude'],  $_POST['ai1ec_exrule'] );
        }
        if (
            isset( $_POST['ai1ec_repeat'] ) &&
            'RDATE' === substr( $_POST['ai1ec_rrule'], 0, 5 )
        ) {
            $_POST['ai1ec_rdate'] = substr( $_POST['ai1ec_rrule'], 6 );
            unset( $_POST['ai1ec_repeat'],  $_POST['ai1ec_rrule'] );
        }
    }

}
