/**
     * product_edit function.
     * 
     * @access public
     * @return void
     */
    function product_edit()
    {
        $this->EE->cp->set_breadcrumb($this->base_url . '&method=product', lang('nav_br_products'));
        // Load Resources Required for custom fields
        $this->EE->lang->loadfile('content');
        $this->EE->load->library('api');
        $this->EE->api->instantiate('channel_fields');
        $this->EE->api->instantiate('channel_entries');
        $this->EE->load->library('filemanager');
        $this->EE->load->library('spellcheck');
        $this->EE->load->library('file_field');
        $this->EE->load->model('channel_model');
        $this->EE->load->helper(array('snippets', 'typography', 'spellcheck'));
        $this->EE->file_field->browser();
        $this->EE->cp->get_installed_modules();
        // Load channel data
        $this->_channel_data = $this->_load_channel_data($this->br_channel_id);
        // Setup the file list for custom fields
        $this->_setup_file_list();
        $this->vars["file_list"] = $this->_file_manager['file_list'];
        $this->EE->cp->add_js_script(array('ui' => array('datepicker', 'resizable', 'draggable', 'droppable'), 'plugin' => array('markitup', 'toolbox.expose', 'overlay', 'tmpl', 'ee_url_title'), 'file' => array('json2', 'cp/publish', 'cp/publish_tabs')));
        // Set the Breadcrumb
        $this->EE->cp->set_breadcrumb($this->base_url . '&method=product', lang('nav_br_products'));
        // Lets setup a new product flag. If we are going to edit the product flip
        // to FALSE so that we can differeniate in certain places when needed.
        $new_product = TRUE;
        $product_id = 0;
        $entry_id = 0;
        // Get the upload preferences
        $this->EE->load->model('tools_model');
        $this->_get_upload_preferences($this->EE->session->userdata('group_id'), $entry_id);
        // If we were passed a GET product_id and entry_id then
        // we are editind
        if (isset($_GET["product_id"]) && isset($_GET["entry_id"])) {
            $new_product = FALSE;
            $product_id = $_GET["product_id"];
            $entry_id = $_GET["entry_id"];
        }
        // Custom Channel Fields
        $this->vars["custom"] = array();
        // Setup some helpers
        $this->vars["spell_enabled"] = TRUE;
        $this->vars["smileys_enabled"] = isset($this->EE->cp->installed_modules['emoticon']) ? TRUE : FALSE;
        if ($this->vars["smileys_enabled"]) {
            $this->EE->load->helper('smiley');
            $this->EE->cp->add_to_foot(smiley_js());
        }
        // Glossary Items
        $this->vars['glossary_items'] = $this->EE->load->ee_view('content/_assets/glossary_items', '', TRUE);
        // Set the global javascript (Content Publish Method)
        $this->_set_global_js($entry_id);
        // Get current data if its an edit
        $data = array();
        if ($new_product == FALSE) {
            // Get the data for the entry_id
            $prefix = $this->EE->db->dbprefix;
            $sql = "SELECT \n\t\t\t\t\t\t\t\t\td.* \n\t\t\t\t\t\t\t\tFROM \n\t\t\t\t\t\t\t\t\t" . $prefix . "br_product_entry p, \n\t\t\t\t\t\t\t\t\t" . $prefix . "channel_data d \n\t\t\t\t\t\t\t\tWHERE \n\t\t\t\t\t\t\t\t\tp.entry_id = d.entry_id \n\t\t\t\t\t\t\t\tAND \n\t\t\t\t\t\t\t\t\tp.product_id = " . $product_id;
            $qry = $this->EE->db->query($sql);
            $result = $qry->result_array();
            // Data array holds the field data
            // in field_id_# key => val format
            $data = $result[0];
        }
        // Get the fields for the channel
        $fields = $this->EE->api_channel_fields->setup_entry_settings($this->br_channel_id, $data, FALSE);
        // Build the inputs
        $fields = $this->_prep_field_wrapper($fields);
        // Now that we support RTE lets load up the required js.
        if (version_compare(APP_VER, '2.5', '>=')) {
            $rte_js = $this->EE->functions->fetch_site_index() . QUERY_MARKER . 'ACT=' . $this->EE->cp->fetch_action_id('Rte', 'get_js') . '&toolset_id=0' . '&cp=y' . '&selector=' . urlencode(".rte");
            $this->EE->cp->add_to_foot('<script type="text/javascript" src="' . $rte_js . '"></script>');
            $this->EE->cp->add_to_head('<link href="' . $this->EE->config->item('theme_folder_url') . 'cp_themes/default/css/rte.css" rel="stylesheet" media="all" />');
        }
        $i = 0;
        foreach ($fields as $f) {
            if (isset($f["field_name"])) {
                $this->EE->api_channel_fields->set_settings($f["field_type"], $f);
                $this->EE->api_channel_fields->setup_handler($f["field_id"]);
                // Either put in existing data or nothing on new product
                $param[0] = $new_product == FALSE ? $data["field_id_" . $f["field_id"]] : "";
                // Hack added to deal with double encoding issue
                // from rte. Yuck but what can you do? - dpd
                $param[0] = form_prep($param[0], "field_id_" . $f["field_id"]);
                $this->vars["custom"][$i] = array('settings' => $f, 'display_field' => $this->EE->api_channel_fields->apply('display_field', $param));
                $i++;
            }
        }
        if ($new_product == FALSE) {
            $this->vars['cp_page_title'] = lang('br_product_edit') . ' [' . $product_id . ']';
        } else {
            $this->vars['cp_page_title'] = lang('nav_br_products');
        }
        // Generate the list of products based
        // on the search terms provided.
        // Get the products
        if ($new_product == FALSE) {
            $products = $this->EE->product_model->get_products($product_id, 1);
            // Since we are now allowing product type changing
            // we need to set some defaults on the edit form as
            // well. We should probably match both instances (new/edit)
            // but lets just get it started to test it out. -dpd
            if (!isset($products[0]["donation"][0])) {
                // some defaults for donations
                $products[0]["donation"][0] = array('min_donation' => 10, 'allow_recurring' => 0);
            }
            // We know the type
            $fields = array();
            $values = '<tr>';
            if (isset($products[0]["configurable"])) {
                foreach ($products[0]["configurable"] as $c) {
                    foreach ($c["attribute"] as $val) {
                        $fields[$val["attribute_id"]] = $val["attribute_id"];
                        // build the configurable attributes into the row
                        $values .= '<td>
													<input type="hidden" name="config_attr_' . $val["attribute_id"] . '[]" value="' . $val["option_id"] . '" />' . $this->_option_to_label($val["option_id"]) . '
												</td>';
                    }
                    // Basic inputs
                    $values .= '	<td>
												<input type="text" name="config_sku[]" value="' . $c["sku"] . '" /></td>
											<td>
												<input type="text" name="config_qty[]" value="' . $c["qty"] . '" /></td>
											<td>
												<select style="display:none" name="config_adjust_type[]">';
                    $sel = $c["adjust_type"] == 'fixed' ? 'selected="selected"' : '';
                    $values .= '<option ' . $sel . '>fixed</option>';
                    $sel = $c["adjust_type"] == 'percent' ? 'selected="selected"' : '';
                    $values .= '<option ' . $sel . '>percent</option>';
                    $values .= '		</select>
												<input type="text" name="config_adjust[]" value="' . $c["adjust"] . '" /></td>
											<td class="move_config_row">
												<img src="' . $this->_theme('images/move.png') . '" /></td>
											<td>
												<input type="hidden" name="config_configurable_id[]" value="' . $c["configurable_id"] . '" />
												<a href="#" class="config_item_remove"><img src="' . $this->_theme('images/delete.png') . '" alt="' . lang('br_delete') . '" /></a></td>
										</tr>';
                }
            }
            // if its configurable
            if ($products[0]["type_id"] == 3) {
                $this->vars["config_products"] = $this->_build_configurable_form($fields, $values);
            }
            $product_feeds = $this->EE->product_model->get_feed_id_by_product($product_id);
            if ($products[0]["sale_start"] == '0000-00-00 00:00:00') {
                $products[0]["sale_start"] = '';
            } else {
                if ($products[0]["sale_start"] != null) {
                    $products[0]["sale_start"] = date("m/d/y", strtotime($products[0]["sale_start"]));
                }
            }
            if ($products[0]["sale_end"] == '0000-00-00 00:00:00') {
                $products[0]["sale_end"] = '';
            } else {
                if ($products[0]["sale_end"] != null) {
                    $products[0]["sale_end"] = date("m/d/y", strtotime($products[0]["sale_end"]));
                }
            }
            $this->vars['product_feeds'] = $product_feeds;
            $this->vars['products'] = $products;
            $this->vars["title"] = $products[0]["title"];
            $this->vars["hidden"] = array('site_id' => $this->site_id, 'type_id' => $products[0]["type_id"], 'product_id' => $products[0]["product_id"], 'entry_id' => $entry_id);
            // Get the available member groups
            $qry = $this->EE->member_model->get_member_groups();
            $groups = array();
            foreach ($qry->result_array() as $row) {
                $groups[] = $row;
            }
            $this->vars["groups"] = $groups;
            if ($this->vars['products'][0]['type_id'] != 3) {
                $this->vars["config_opts"] = $this->EE->product_model->get_attribute_config();
                $this->vars["config_opts_link"] = $this->ajax_url . $this->EE->cp->fetch_action_id('Brilliant_retail_mcp', 'product_configurable_create_options');
            }
            // Experimental!
            //
            // This will allow you to switch the product type on the edit
            // form? -dpd
            //
            if ($this->EE->config->item('br_product_edit_type') === TRUE) {
                $options = '<select id="type_id" name="type_id">';
                foreach ($this->vars['product_type'] as $key => $val) {
                    $sel = $products[0]['type_id'] == $key ? 'selected' : '';
                    $options .= '<option value="' . $key . '" ' . $sel . '>' . $val . '</option>';
                }
                $options .= '</select>';
                $this->vars["type"] = $options;
                $this->vars["sub_type"] = $this->_get_sub_type($this->vars['products'][0]['type_id'], TRUE);
            } else {
                $this->vars["type"] = $this->_config['product_type'][$this->vars['products'][0]['type_id']];
                $this->vars["sub_type"] = $this->_get_sub_type($this->vars['products'][0]['type_id']);
            }
            $this->vars["attrs"] = $this->_product_attrs($this->vars['products'][0]["attribute_set_id"], $this->vars['products'][0]["product_id"]);
            $this->vars["attribute_sets"] = $this->EE->product_model->get_attribute_sets();
            $this->vars['add_attributes'] = $this->ajax_url . $this->EE->cp->fetch_action_id('Brilliant_retail_mcp', 'product_add_atributes');
            $this->vars["options"] = $this->_product_options($this->vars['products'][0]["product_id"]);
            // Get the images
            $images = $this->EE->product_model->get_product_images($this->vars['products'][0]["product_id"], FALSE);
            // Remove the large / thumb values
            unset($images["image_large"]);
            unset($images["image_large_title"]);
            unset($images["image_thumb"]);
            unset($images["image_thumb_title"]);
            $this->vars["images"] = $images;
            // Get Categories
            // First get the categories that
            // apply to this product
            $selected = $this->EE->product_model->get_category_list($this->vars['products'][0]["product_id"]);
            // Get them all
            $cat = $this->EE->product_model->get_categories(0);
            // Create a tree
            $categories = lang('br_no_product_categories');
            if (isset($cat[0])) {
                $categories = $this->_product_category_tree($cat[0], $cat, 0, $selected);
            }
            $this->vars["categories"] = $categories;
        } else {
            // Build an empty product shell
            $p = new Product();
            $products = $p->createshell();
            $this->vars["products"] = $products;
            $this->vars['product_feeds'] = array();
            // Generate the list of products based
            // on the search terms provided.
            $this->vars["type_id"] = 0;
            // Set the type options
            $options = '<select id="type_id" name="type_id">';
            foreach ($this->vars['product_type'] as $key => $val) {
                $options .= '<option value="' . $key . '">' . $val . '</option>';
            }
            $options .= '</select>';
            $this->vars["type"] = $options;
            // member groups for the price matrix
            $qry = $this->EE->member_model->get_member_groups();
            $groups = array();
            foreach ($qry->result_array() as $row) {
                $groups[] = $row;
            }
            $this->vars["groups"] = $groups;
            // some defaults for configurable products
            $this->vars["config_opts"] = $this->EE->product_model->get_attribute_config();
            $this->vars["config_opts_link"] = $this->ajax_url . $this->EE->cp->fetch_action_id('Brilliant_retail_mcp', 'product_configurable_create_options');
            // some defaults for donations
            $this->vars["products"][0]["donation"][0] = array('min_donation' => 10, 'allow_recurring' => 0);
            // get the sub_type
            $this->vars["sub_type"] = $this->_get_sub_type();
            // No Attributes by default
            $this->vars["attribute_sets"] = $this->EE->product_model->get_attribute_sets();
            $this->vars['add_attributes'] = $this->ajax_url . $this->EE->cp->fetch_action_id('Brilliant_retail_mcp', 'product_add_atributes');
            $this->vars["attrs"] = '';
            $this->vars["options"] = array();
            $this->vars["images"] = array();
            $this->vars['title'] = lang('br_new_product');
            $this->vars['hidden'] = array('site_id' => $this->site_id, 'product_id' => 0, 'type_id' => 0);
            // Get Categories
            $cat = $this->EE->product_model->get_categories(0);
            // Create a tree
            if (isset($cat[0])) {
                $categories = $this->_product_category_tree($cat[0], $cat, 0);
            } else {
                $categories = array();
            }
            $this->vars["categories"] = $categories;
        }
        // What editor should we use for the detail field
        $this->EE->load->library('product_form');
        $this->vars["detail_field"] = $this->EE->product_form->select_editor($products[0]["detail"]);
        $this->_markitup();
        $this->vars['feeds'] = $this->EE->feed_model->get_feeds();
        $this->vars["tab"]["main"] = $this->_view('product/tabs/main', $this->vars);
        $this->vars["tab"]["detail"] = $this->_view('product/tabs/detail', $this->vars);
        // Include the attributes unless they were hidden
        if ($this->EE->config->item('br_product_hide_attribute') !== TRUE) {
            $this->vars["tab"]["attributes"] = $this->_view('product/tabs/attributes', $this->vars);
        }
        // Include the options unless they were hidden
        if ($this->EE->config->item('br_product_hide_option') !== TRUE) {
            $this->vars["tab"]["option"] = $this->_view('product/tabs/option', $this->vars);
        }
        // Include the images unless they were hidden
        if ($this->EE->config->item('br_product_hide_image') !== TRUE) {
            $this->vars["tab"]["image"] = $this->_view('product/tabs/image', $this->vars);
        }
        $this->vars["tab"]["price"] = $this->_view('product/tabs/price', $this->vars);
        $this->vars["tab"]["sale_price"] = $this->_view('product/tabs/sale_price', $this->vars);
        $this->vars["tab"]["category"] = $this->_view('product/tabs/category', $this->vars);
        #$this->vars["tab"]["addon"] 		= $this->_view('product/tabs/addon', $this->vars);
        // Include the related products unless they were hidden
        if ($this->EE->config->item('br_product_hide_related') !== TRUE) {
            $this->vars["tab"]["related"] = $this->_view('product/tabs/related', $this->vars);
        }
        $this->vars["tab"]["seo"] = $this->_view('product/tabs/seo', $this->vars);
        // Include the product feed unless they were hidden
        if ($this->EE->config->item('br_product_hide_feed') !== TRUE) {
            $this->vars["tab"]["feed"] = $this->_view('product/tabs/feed', $this->vars);
        }
        // Want to do something to the edit form before we show it to the world?
        // Added 1.1.5.0 DPD
        if ($this->EE->extensions->active_hook('br_product_editform_before') === TRUE) {
            $this->vars = $this->EE->extensions->call('br_product_editform_before', $this->vars);
        }
        $this->EE->javascript->compile();
        // Set the form action
        $this->vars["action"] = 'C=addons_modules&M=show_module_cp&module=brilliant_retail&method=product_update';
        return $this->_view('product/edit', $this->vars);
    }