<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Shop_Admin extends MY_Controller
{
	private $sites;
	private $data = array("show_menu" => true);

	public function __construct()
	{
		parent::__construct();

		$this->current_user = get_user();
		$this->data["user"] = $this->current_user;
		$this->sites = $this->site->get();
		$this->data["sites"] = $this->sites;

		$this->admin_login_required();
		$this->init();
	}

	private function init()
	{
		$this->load->model(array("site", "page"));

		if(!Mainframe::adminInit())
		{
			die("This website has not been configured yet.  Please check back shortly!");
		}

		$site = Mainframe::site();
		$this->sites = $this->site->get();

		$key = "module_js:" . Mainframe::active_site_id() . ":" . $this->current_user->user_id;

		if(($module_js = $this->cache->get($key)) === false)
		{
			$modules = $this->moduleinstance->LoadBySiteID(Mainframe::active_site_id(), "tag", $this->current_user);
			$module_js = "[";

			foreach($modules as $module)
			{
				$module_js .= "[\"$module->tag ($module->name)\", $module->module_instance_id], ";
			}
			$module_js = substr($module_js, 0, strlen($module_js)-2);
			$module_js .= "]";

			if($module_js == "]")
			{
				$module_js = "null";
			}

			$this->cache->save($key, $module_js, 86400);
		}

		Mainframe::setModuleJS($module_js);

		return true;
	}

	public function index()
	{
		$this->load->model("template");

		$site = Mainframe::site();
		$template = new Template();
		$template->Load($site->template_id);
		Mainframe::setTemplate($template);

		if(!$template->template_id || !file_exists(TEMPLATE_PATH . "/$template->directory/index.php"))
		{
			FeralRedirect("/admin/templates");
		}

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/dashboard", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	/* generic functions
	 * Most list and delete functions are identical except for the class and ID used.
	 * The "generic" functions will be called from the specific functions when possible to save tons of duplicate code.
	*/
	public function generic_list($model, $dataset)
	{
		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/" . $model . "_list", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function generic_delete($model, $models, $id="")
	{
		$this->load->model("$model");

		if(!$id)
		{
			$id = get_id();// $this->input->get($model . "_id");
		}

		if($id)
		{
			//get the class name so we know what object to create
			$class = ucwords($model);
			$obj = new $class();
			$obj->load($id);

			//format the class name pretty for display
			$class = ucwords(str_replace("_", " ", $class));

			if($obj->delete())
			{
				$this->messages[] = "$class Deleted";
			}
			else
			{
				$this->errors[] = "Error Deleting $class<br /><br />You can't delete a $class that has data linked to it.";
			}
		}

		$this->{$models}();
	}
	/* end generic functions */

	/* config functions */
	public function config()
	{
		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_config", "page", "shop/shop_category_layout"));

		$id = get_id();

		$config = $this->shop_config->LoadBySiteID(Mainframe::active_site_id());
		$pages = $this->page->LoadBySiteID(Mainframe::active_site_id(), $this->current_user);
		$category_layouts = $this->shop_category_layout->get();

		$this->data["id"] = $id;
		$this->data["config"] = $config;
		$this->data["pages"] = $pages;
		$this->data["category_layouts"] = $category_layouts;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/config", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function config_save()
	{
		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_config");

		$config = $this->shop_config->LoadBySiteID(Mainframe::active_site_id());

		foreach($config as $option)
		{
			$c = new Shop_Config();
			$c->Load($option->config_id);
			$c->config_value = $this->input->post("config_" . $option->config_id);
			$c->save();
		}
		$this->cache->clean();

		$this->messages[] = "Configuration Saved";

		if($this->input->post("submit_action") == "continue")
		{
			$this->config();
		}
		else
		{
			$this->index();
		}
	}
	/* end config functions */

	/* category functions */
	public function categories()
	{
		if(!$this->current_user->has(ACTION_SHOP_CATEGORIES))
		{
			return $this->denied($this->data);
		}

		$this->generic_list("category", "categories");
	}

	public function category($category_id=null)
	{
		if(!$this->current_user->has(ACTION_SHOP_CATEGORIES))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("page", "shop/shop_category", "shop/shop_category_layout", "shop/shop_product_layout", "shop/shop_image", "shop/shop_category_shopper_group"));

		$id = ($category_id ? $category_id : get_id());

		$category = new Shop_Category();
		$category->LoadWithImages($id, false);

		$pages = $this->page->LoadBySiteID(Mainframe::active_site_id(), $this->current_user);

		$layouts = $this->shop_category_layout->get();
		$product_layouts = $this->shop_product_layout->get();
		$categories = $this->shop_category->LoadBySiteID(Mainframe::active_site_id());
		$shopper_groups = $this->shop_category_shopper_group->LoadBySiteIDWithLinks(Mainframe::active_site_id(), $category->category_id);

	// 	$images = $this->shop_image->LoadBySiteID(Mainframe::active_site_id());

	// 	$select_values = array();
	// 	$image_array = array();
	// 	$width = 100;
	// 	$height = 75;

	// 	foreach($images as $image)
	// 	{
	// 		$new_filename = preg_replace('/\.(jpe?g|png|gif|bmp|JPE?G|PNG|GIF|BMP)$/', "_" . $width . "x" . $height . '.\1', $image->filename);

	// 		if(file_exists(ABSOLUTE_PATH . "/images/shop/" . $image->filename))
	// 		{
	// 			$image_array[] = $image->filename;
	// 			$select_values[$image->image_id] = LIVE_SITE . "/images/shop/resized/" . $new_filename;
	// 		}
	// 	}
	// 	$select_values = array_unique($select_values);

	// //process_thumbnails($image_array, $width, $height);

	// 	$image_data = array("select_id" => "category_image_id", "selected_value" => $category->category_image_id, "select_values" => $select_values, "height" => $height);

		$this->data["id"] 				= $id;
		$this->data["category"] 			= $category;
		$this->data["categories"] 		= $categories;
		$this->data["layouts"] 			= $layouts;
		$this->data["product_layouts"] 	= $product_layouts;
		$this->data["pages"] 				= $pages;
		$this->data["shopper_groups"] 	= $shopper_groups;
		//$this->data["image_data"] 		= $image_data;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/category_edit", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function category_save()
	{
		if(!$this->current_user->has(ACTION_SHOP_CATEGORIES))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_category", "shop/shop_image", "shop/shop_shopper_group", "shop/shop_category_shopper_group", "shop/shop_route", "redirect"));

		$category_id = $this->input->post("category_id");

		$category = new Shop_Category();
		$category->Load($category_id);
		$old_url = $category->GetURL();
		$category->readPostVars();
		$saved = $category->save();
		$this->cache->clean();

		$groups = $this->shop_shopper_group->LoadBySiteID(Mainframe::active_site_id());

		foreach($groups as $group)
		{
			if($this->input->post("shopper_group_" . $group->shopper_group_id) == 1)
			{
				$this->shop_category_shopper_group->add_link($category->category_id, $group->shopper_group_id);
			}
			else
			{
				$this->shop_category_shopper_group->delete_link($category->category_id, $group->shopper_group_id);
			}
		}

		$config = array();
		$config['upload_path'] = ABSOLUTE_PATH . '/images/shop/';
		$config['allowed_types'] = 'gif|jpg|jpeg|png';
		$config['max_size']	= '5242880';	//5MB
		$config['encrypt_name']	= true;
		$config['remove_spaces'] = true;
		$config['overwrite'] = false;
		//$config['max_width']  = '1024';
		//$config['max_height']  = '768';
		//
		$this->load->library('upload', $config);

		if($this->upload->do_upload("category_image"))
		{
			$upload_data = array('upload_data' => $this->upload->data());

			$image = new Shop_Image();
			$image->LoadByFilename($upload_data["upload_data"]["file_name"]);	//just in case it exists
			$image->site_id = Mainframe::active_site_id();
			$image->product_id = null;
			$image->filename = $upload_data["upload_data"]["file_name"];
			$image->save();

			$category->category_image_id = $image->image_id;
			$category->save();

			process_thumbnails(array($upload_data["upload_data"]["file_name"]), 200, 125);
		}

		$old_routes = $this->shop_route->load_by_url_fragment(Mainframe::site()->site_id, $old_url);
		$this->shop_route->build_category_route($category);
		// Reload to get the updated route, if necessary.
		$category->load($category->category_id);
		$new_url = $category->GetURL();

		if($old_url && $old_url != $new_url)
		{
			foreach($old_routes as $r)
			{
				$r->new_url = str_replace($old_url, $new_url, $r->url);

				$redirect = new Redirect();
				$redirect->site_id = Mainframe::site()->site_id;
				$redirect->old_url = $r->url;
				$redirect->new_url = $r->new_url;
				$redirect->save();
			}
		}

		if($saved)
		{
			$this->messages[] = "Category Saved";
		}
		else
		{
			$this->errors[] = "Error Saving Category";
		}

		if($this->input->post("submit_action") == "continue")
		{
			$this->category($category->category_id);
		}
		else
		{
			$this->categories();
		}
	}

	public function category_delete()
	{
		if(!$this->current_user->has(ACTION_SHOP_CATEGORIES))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_category", "shop/shop_route"));

		$id = get_id();

		if($id)
		{
			$obj = new Shop_Category();
			$obj->load($id);

			if(strlen($obj->datasource_category_id) > 0)
			{
				$obj->published = 0;
				$obj->save();

				$this->shop_route->build_category_route($obj);

				$this->data["message"] = "This category is linked to a data source so it was unpublished instead of deleted.";
			}
			else
			{
				$this->shop_route->build_category_route($obj);

				if($obj->delete())
				{
					$this->messages[] = "Category Deleted";
				}
				else
				{
					$this->errors[] = "Error Deleting Category<br /><br />You can't delete a category that has products in it.";
				}
			}
		}

		$this->categories();
	}
	/* end category functions */

	/* product functions */
	public function products()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_product", "shop/shop_category"));

		$categories = $this->shop_category->LoadBySiteID(Mainframe::active_site_id());
		$this->data["categories"] = $categories;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/product_list", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function product($product_id=null)
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("document", "shop/shop_product", "shop/shop_category", "shop/shop_category_layout", "shop/shop_product_layout", "shop/shop_image", "shop/shop_vehicle", "shop/shop_price", "shop/shop_shopper_group", "shop/shop_product_variant"));

		$id = ($product_id ? $product_id : get_id());

		$product = new Shop_Product();
		$product->LoadForAdmin($id);

		$prices 		= $this->shop_price->LoadProductPrices($product->product_id);
		$layouts 		= $this->shop_product_layout->get();
		$categories 	= $this->shop_category->LoadByProductID($product->product_id);
		//$images 		= $this->shop_image->LoadBySiteID(Mainframe::active_site_id());
		$extra_images 	= $this->shop_image->LoadByProductID($product->product_id);
		$years 			= $this->shop_vehicle->GetYears();

		$product->prices 	= $prices;
		$product->variants 	= $this->shop_product_variant->LoadAllByProductID($product->product_id);
		$shopper_groups  	= $this->shop_shopper_group->LoadBySiteID(Mainframe::active_site_id());

		// Only Jensen Trailers uses this, but this allows them to update safely.
		if(file_exists(APPLICATION_PATH . "/models/shop/Shop_product_size.php"))
		{
			$this->load->model("shop/shop_product_size");
			$sizes 			= $this->shop_product_size->load_selected_by_product_id($product->product_id);
			$this->data["sizes"] 	= $sizes;
		}

		foreach($extra_images as $img)
		{
			process_thumbnails(array($img->filename), 200, 125);
		}

 		$files = $this->document->loadByDirectory(Mainframe::active_site_id(), DOCUMENT_PATH, $this->current_user);
 		$files_options = "";

		foreach($files as $file)
		{
			$files_options .= '<option value="' . addslashes($file->url) . '">' . $file->title . '</option>';
		}

		$default_tab = ($this->input->get_post("default_tab") != "" ? $this->input->get_post("default_tab") : 0);

		$this->data["id"] 			= $id;
		$this->data["product"] 		= $product;
		$this->data["categories"] 	= $categories;
		$this->data["layouts"] 		= $layouts;
		$this->data["years"] 			= $years;
		//$this->data["image_data"] 	= $image_data;
		$this->data["files_options"] 	= $files_options;
		$this->data["default_tab"] 	= $default_tab;
		$this->data["extra_images"] 	= $extra_images;
		$this->data["prices"] 		= $prices;
		$this->data["shopper_groups"] 	= $shopper_groups;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/product_edit", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function product_save()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$product_variants 	= json_decode($this->input->post("product_variants"));
		$product_prices 	= json_decode($this->input->post("product_prices"));

		$this->load->model(array("shop/shop_product", "shop/shop_category", "shop/shop_image", "shop/shop_category_product", "shop/shop_product_layout", "shop/shop_vehicle", "shop/shop_price", "shop/shop_route", "redirect", "document_log", "shop/shop_product_variant"));

		$this->load->library("upload");
		$this->load->helper("url");

		$config = array();
		$config['upload_path'] = ABSOLUTE_PATH . '/images/shop/';
		$config['allowed_types'] = 'gif|jpg|jpeg|png';
		$config['max_size']	= '26214400';	//25MB
		$config['encrypt_name']	= true;
		$config['remove_spaces'] = true;
		$config['overwrite'] = false;
		//$config['max_width']  = '1024';
		//$config['max_height']  = '768';
		//

		$product_id = $this->input->post("product_id");

		$product = new Shop_Product();
		$product->Load($product_id);
		$old_url = $product->GetURL();
		$product->readPostVars();
		$product->last_modified = date("Y-m-d H:i:s");
		$saved = $product->save();
		$this->cache->clean();

		// Only Jensen Trailers uses this, but this allows them to update safely.
		if(file_exists(APPLICATION_PATH . "/models/shop/Shop_product_size.php"))
		{
			$this->load->model("shop/shop_product_size");
			$sizes = $this->shop_product_size->get();

			foreach($sizes as $size)
			{
				if($this->input->post("size_" . $size->product_size_id) > 0)
				{
					$this->shop_product_size->add_link($product->product_id, $size->product_size_id);
				}
				else
				{
					$this->shop_product_size->delete_link($product->product_id, $size->product_size_id);
				}
			}
		}

		$variant_map = array();
		$variant_ids = array();

		foreach($product_variants as $v)
		{
			$variant = new Shop_product_variant();

			if(is_numeric($v->product_variant_id))
			{
				$variant->load($v->product_variant_id);
			}

			$variant->product_id 	= $product->product_id;
			$variant->variant 		= $v->variant;
			$variant->sort 			= $v->sort;
			$variant->save();
			$variant_ids[] 			= $variant->product_variant_id;

			// Save a map of our temporary IDs to link up with prices later.
			if(preg_match('/^new/', $v->product_variant_id))
			{
				$variant_map[$v->product_variant_id] = $variant->product_variant_id;
			}
		}

		if(count($variant_ids))
		{
			$this->shop_product_variant->delete_others($product->product_id, $variant_ids);
		}
		else
		{
			$this->shop_product_variant->delete_all($product->product_id);
		}

		$price_ids = array();

		foreach($product_prices as $p)
		{
			$price = new Shop_price();

			if(is_numeric($p->price_id))
			{
				$price->load($p->price_id);
			}

			$price->product_id 			= $product->product_id;
			$price->product_variant_id 	= $p->product_variant_id;
			$price->shopper_group_id 	= $p->shopper_group_id;
			$price->price 				= ($p->price > 0 ? $p->price : NULL);

			if(preg_match('/^new/', $price->product_variant_id))
			{
				$price->product_variant_id = $variant_map[$price->product_variant_id];
			}

			$price->save();
			$price_ids[] = $price->price_id;
		}

		if(count($price_ids))
		{
			$this->shop_price->delete_others($product->product_id, $price_ids);
		}
		else
		{
			$this->shop_price->delete_all($product->product_id);
		}

		// $prices = $this->shop_price->LoadProductPrices($product->product_id);

		// foreach($prices as $price)
		// {
		// 	if($this->input->post("price_" . $price->shopper_group_id) > 0)
		// 	{
		// 		$this->shop_price->add_price($product->product_id, $price->shopper_group_id, $this->input->post("price_" . $price->shopper_group_id));
		// 	}
		// 	else
		// 	{
		// 		$this->shop_price->delete_price($product->product_id, $price->shopper_group_id);
		// 	}
		// }

		$categories = $this->shop_category->LoadByProductID($product->product_id);

		foreach($categories as $cat)
		{
			if($this->input->post("category_id_" . $cat->category_id) == 1)
			{
				$this->shop_category_product->add_link($cat->category_id, $product->product_id);
			}
			else
			{
				$this->shop_category_product->delete_link($cat->category_id, $product->product_id);
			}
		}

		$layout_id = $this->input->get_post("layout_id");
		$product_id = $this->input->get_post("product_id");

		$layout = new Shop_Product_Layout();
		$layout->Load($product->product_layout_id);
		$options = $layout->get_layout_options_for_product($product->product_id);

		foreach($options as $option)
		{
			//skip saving file IDs set to zero
			// if($option->datatype == "file" && $this->input->post("product_option_" . $option->key) == 0)
			// {
			// 	//continue;
			// }
			// else
			// {

			//only save options which have been updated
			if($this->input->post("product_option_" . $option->key) != $this->input->post("product_option_" . $option->key . "_old_value"))
			{
				$this->shop_product_layout->save_product_option($product->product_id, $option->key, $this->input->post("product_option_" . $option->key));
			}
			//}

			//in the case of files, previously set ones will be preserved above.  new ones will get re-assigned below
			if($option->datatype == "file")
			{
				$config['upload_path'] = DOCUMENT_PATH . '/';
				$config['allowed_types'] = 'pdf|doc|xls|docx|xlsx';
				$config['encrypt_name']	= false;
				$config['overwrite'] = true;

				$this->upload->initialize($config);

				if($this->upload->do_upload("product_option_" . $option->key . "_file"))
				{
					$this->load->model("document");
					$document 					= new Document();
					$document->site_id 			= Mainframe::active_site_id();
					$document->category_id 		= null;
					$document->title 			= $this->upload->file_name;
					$document->description 		= null;
					$document->filename 		= $this->upload->file_name;

					$document->url 				= preg_replace('/[^a-z0-9\-_]/', '-', strtolower($this->upload->file_name));
					$document->url 				= preg_replace('/-{2,10}/', '-', $document->url);
					$document->url 				= preg_replace('/(^-|-$)/', '', $document->url);

					$document->access 			= 1;
					$document->published 		= 1;
					$document->created 			= date("Y-m-d H:i:s");
					$document->created_user_id 	= $this->current_user->user_id;

					// Check if this URL is available, add numbers on the end if it isn't.
					$count 	= 0;
					$url 	= $document->url;
					do
					{
						$query = $this->db->query("SELECT `document_id` FROM `document` WHERE `document_id` !=? AND `url`=?", array($document->document_id, $url));

						if($query->num_rows() == 0)
						{
							break;
						}

						$count++;
						$url = $document->url . $count;
					}
					while(true);

					$document->url 	= $url;
					$document->save();
					$this->document_log->logChanges(new Document(), $document, $this->current_user);
					$path = "/document/" . $document->url;
					$this->shop_product_layout->save_product_option($product->product_id, $option->key, $path);
				}
			}
		}

		$config['upload_path'] = ABSOLUTE_PATH . '/images/shop/';
		$config['allowed_types'] = 'gif|jpg|jpeg|png';
		$config['encrypt_name']	= true;
		$config['overwrite'] = false;

		$this->upload->initialize($config);

		if($this->upload->do_upload("main_product_image"))
		{
			$upload_data = array('upload_data' => $this->upload->data());

			$main_image = new Shop_Image();
			$main_image->LoadByFilename($upload_data["upload_data"]["file_name"]);	//just in case it exists
			$main_image->site_id = Mainframe::active_site_id();
			$main_image->product_id = $product->product_id;
			$main_image->filename = $upload_data["upload_data"]["file_name"];
			$main_image->save();

			$product->product_image_id = $main_image->image_id;
			$product->save();

			process_thumbnails(array($upload_data["upload_data"]["file_name"]), 200, 125);
		}
		for($i=1; $i<=5; $i++)
		{
			if($this->upload->do_upload("extra_product_image_" . $i))
			{
				$upload_data = array('upload_data' => $this->upload->data());

				$extra_image = new Shop_Image();
				$extra_image->LoadByFilename($upload_data["upload_data"]["file_name"]);	//just in case it exists
				$extra_image->site_id = Mainframe::active_site_id();
				$extra_image->product_id = $product->product_id;
				$extra_image->filename = $upload_data["upload_data"]["file_name"];
				$extra_image->save();

				process_thumbnails(array($upload_data["upload_data"]["file_name"]), 200, 125);
			}
		}

		if($this->input->post("image-sort") != "")
		{
			$image_sort = json_decode($this->input->post("image-sort"));

			foreach($image_sort as $sort)
			{
				$i = new Shop_Image();
				$i->load($sort->image_id);

				// Its possible that an image was removed and therefore doesn't exist anymore.
				if($i->image_id)
				{
					$i->sort = $sort->sort;
					$i->save();
				}
			}
		}

		//look through POST vars for "vehicle_xxx" and make sure a link exists for this product.
		//removing unchecked links is not necessary because they are handled with a table and delete buttons.
		$postvars = $this->input->post();

		foreach($postvars as $key=>$value)
		{
			//this post variable is a vehicle ID
			if(preg_match('/^vehicle_/', $key) && ($value == "1" || $value == "on"))
			{
				$vehicle_id = str_replace("vehicle_", "", $key);
				$this->shop_vehicle->link_to_product($vehicle_id, $product->product_id);
			}
		}

		$this->shop_route->build_product_route($product);
		// Reload to get the updated route, if necessary.
		$product->load($product->product_id);
		$new_url = $product->GetURL();

		if($old_url && $old_url != $new_url)
		{
			$redirect = new Redirect();
			$redirect->site_id = Mainframe::site()->site_id;
			$redirect->old_url = $old_url;
			$redirect->new_url = $new_url;
			$redirect->save();
		}

		if($saved)
		{
			$this->messages[] = "Product Saved";
		}
		else
		{
			$this->errors[] = "Error Saving Product";
		}

		if($this->input->post("submit_action") == "continue")
		{
			$this->product($product->product_id);
		}
		else
		{
			$this->products();
		}
	}

	public function product_delete()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_product", "shop/shop_route"));

		$id = get_id();

		if($id)
		{
			$obj = new Shop_Product();
			$obj->load($id);

			// I don't remember why this was here.  Seems irrelevant?
			// $this->shop_route->build_product_route($obj);

			if($obj->delete())
			{
				$this->messages[] = "Product Deleted";
			}
			else
			{
				$this->errors[] = "Error Deleting Product<br /><br />You can't delete a product that has data linked to it.";
			}
		}

		$this->products();
	}

	public function product_delete_ajax()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_product", "shop/shop_route"));

		$ids 		= explode(",", str_replace("'", "", $this->input->post("product_ids")));
		$success 	= true;

		foreach($ids as $id)
		{
			$obj = new Shop_Product();
			$obj->load($id);

			// I don't remember why this was here.  Seems irrelevant?
			// $this->shop_route->build_product_route($obj);

			if(!$obj->delete())
			{
				$success = false;
			}
		}

		if($success)
		{
			die("SUCCESS");
		}
		else
		{
			die("FAILED");
		}
	}

	public function delete_product_image()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$image_id = $this->input->post("image_id");

		if(!$image_id)
		{
			die("FAILED");
		}
		else
		{
			$this->load->model("shop/shop_image");
			$image = new Shop_Image();
			$image->load($image_id);
			$image->product_id = null;

			if($image->save())
			{
				die("SUCCESS");
			}
			else
			{
				die("FAILED");
			}
		}
	}

	public function product_duplicate()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_product", "shop/shop_category", "shop/shop_category_product", "shop/shop_product_layout", "shop/shop_product_variant", "shop/shop_price"));

		$product_id = $this->input->get_post("id");
		$product1 = new Shop_Product();
		$product1->Load($product_id);

		if(isset($product1->product_id) && $product1->product_id > 0)
		{
			$product2 = clone($product1);
			$product2->product_id = null;
			$product2->product_name .= " (copy)";
			$product2->url .= "2";
			//any products which are linked to a datasource will not have that info cloned
			$product2->datasource_product_id = "";
			$product2->datasource_hash = "";
			$product2->save();

			$categories = $this->shop_category->GetCategoriesForProductID($product1->product_id);

			foreach($categories as $cat)
			{
				$this->shop_category_product->add_link($cat->category_id, $product2->product_id);
			}

			$layout = new Shop_Product_Layout();
			$layout->Load($product1->product_layout_id);

			$options = $layout->get_layout_options_for_product($product1->product_id);

			foreach($options as $option)
			{
				$layout->save_product_option($product2->product_id, $option->key, $option->data_value);
			}

			// Copy product variants.
			$variants = $this->shop_product_variant->loadByProductID($product1->product_id);
			$variant_map = array();

			foreach($variants as $v)
			{
				$variant = new Shop_product_variant();
				$variant->load($v->product_variant_id);
				$variant->product_variant_id = null;
				$variant->product_id = $product2->product_id;
				$variant->save();
				// Save the old variant ID to new variant ID mapping for cloning the prices.
				$variant_map[$v->product_variant_id] = $variant->product_variant_id;
			}

			// Copy product prices.
			$prices = $this->shop_price->LoadProductPrices($product1->product_id);

			foreach($prices as $p)
			{
				$price = new Shop_price();
				$price->load($p->price_id);
				$price->price_id = null;
				$price->product_id = $product2->product_id;
				// Link to the new variant ID via its old mapping.
				$price->product_variant_id = $variant_map[$p->product_variant_id];
				$price->save();
			}

			redirect("/shop_admin/product?id=" . $product2->product_id);

			return true;
		}

		return false;
	}
	/* end product functions */

	/* order functions */
	public function orders()
	{
		if(!$this->current_user->has(ACTION_SHOP_ORDERS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_order", "shop/shop_order_status"));


		$orders = $this->shop_order->get();
		$this->data["orders"] = $orders;

		$statuses = $this->shop_order_status->get();
		$this->data["statuses"] = $statuses;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/order_list", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function order()
	{
		if(!$this->current_user->has(ACTION_SHOP_ORDERS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_order"));

		$id = get_id();

		$order = new Shop_Order();
		$order->LoadWithDetails($id);

		$this->data["id"] = $id;
		$this->data["order"] = $order;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/order", $this->data);
		$this->load->view("common/footer", $this->data);
	}
	/* end order functions */

	/* AJAX product features */
	public function product_publish()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_product");
		$product_ids = $this->input->get_post("product_ids");
		$result = $this->shop_product->publish_products($product_ids);
		die($result === true ? "SUCCESS" : "FAILED");
	}

	public function product_unpublish()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_product");
		$product_ids = $this->input->get_post("product_ids");
		$result = $this->shop_product->unpublish_products($product_ids);
		die($result === true ? "SUCCESS" : "FAILED");
	}

	public function product_update_price()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_product");
		$product_ids = $this->input->get_post("product_ids");
		$price = $this->input->get_post("price");
		$price_lock = $this->input->get_post("price_lock");
		$update_price_lock = $this->input->get_post("update_price_lock");

		if($update_price_lock == "1")
		{
			$result = $this->shop_product->update_field($product_ids, "price_lock", $price_lock == "1" ? "1" : "0");
		}

		die("SUCCESS");
	}

	public function product_update_size()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_product");
		$product_ids = $this->input->get_post("product_ids");
		$shipping_length = $this->input->get_post("shipping_length");
		$update_shipping_length = $this->input->get_post("update_shipping_length");
		$shipping_width = $this->input->get_post("shipping_width");
		$update_shipping_width = $this->input->get_post("update_shipping_width");
		$shipping_height = $this->input->get_post("shipping_height");
		$update_shipping_height = $this->input->get_post("update_shipping_height");
		$shipping_weight = $this->input->get_post("shipping_weight");
		$update_shipping_weight = $this->input->get_post("update_shipping_weight");

		if($update_shipping_length == "1")
		{
			$result = $this->shop_product->update_field($product_ids, "shipping_length", $shipping_length);
		}

		if($update_shipping_width == "1")
		{
			$result = $this->shop_product->update_field($product_ids, "shipping_width", $shipping_width);
		}

		if($update_shipping_height == "1")
		{
			$result = $this->shop_product->update_field($product_ids, "shipping_height", $shipping_height);
		}

		if($update_shipping_weight == "1")
		{
			$result = $this->shop_product->update_field($product_ids, "shipping_weight", $shipping_weight);
		}

		die("SUCCESS");
	}

	public function product_update_category()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_product", "shop/shop_category_product"));
		$product_ids = $this->input->get_post("product_ids");
		$product_ids_array = explode(",", str_replace("'", "", $this->input->get_post("product_ids")));
		$category_id = $this->input->get_post("category_id");

		if($product_ids == "" || $category_id == "")
		{
			die("FAILED");
		}

		//remove the existing product link for each product's main category ID
		//then create a new link for the new category
		foreach($product_ids_array as $product_id)
		{
			$p = new Shop_Product();
			$p->Load($product_id);

			$this->shop_category_product->delete_link($p->main_category_id, $product_id);
			$this->shop_category_product->add_link($category_id, $product_id);
		}

		//update main category field
		$result = $this->shop_product->update_field($product_ids, "main_category_id", $category_id);

		die("SUCCESS");
	}

	public function order_update_status()
	{
		if(!$this->current_user->has(ACTION_SHOP_ORDERS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_order");
		$order_ids 			= $this->input->get_post("order_ids");
		$status_id 			= $this->input->get_post("status_id");
		$paid 				= $this->input->get_post("paid");
		$tracking_number1 	= $this->input->get_post("tracking_number1");
		$tracking_number2 	= $this->input->get_post("tracking_number2");
		$tracking_number3 	= $this->input->get_post("tracking_number3");

		$this->shop_order->update_status($order_ids, $status_id);

		//$ids is in the format SQL wants for LIKE
		//ie: '1','2','3'
		$ids = explode(",", $order_ids);

		//If any tracking numbers are present, fire an event.
		if($tracking_number1 != "" || $tracking_number2 != "" || $tracking_number3 != "" || $paid !== "")
		{
			foreach($ids as $id)
			{
				$clean_id = trim(str_replace("'", "", $id));

				//remove quotes from around the number
				$order = new Shop_Order();
				$order->load($clean_id);

				if($tracking_number1 != "")
				{
					$order->add_tracking_number($tracking_number1);
				}
				if($tracking_number2 != "")
				{
					$order->add_tracking_number($tracking_number2);
				}
				if($tracking_number3 != "")
				{
					$order->add_tracking_number($tracking_number3);
				}
				if($paid !== "")
				{
					$order->paid = ($paid ? 1 : 0);
				}
				$order->save();

				if($tracking_number1 != "" || $tracking_number2 != "" || $tracking_number3 != "")
				{
					tracking_info_added($clean_id);
				}
			}
		}

		die("SUCCESS");
	}
	/* end AJAX product features */

	public function generate_image_cache()
	{
		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		ini_set("memory_limit", "256M");
		ini_set("output_buffering", "0");
		ini_set("implicit_flush", "1");
		//ini_set("ignore_user_abort", "1");
		ini_set("track_errors", "1");
		ob_implicit_flush(true);

		while (@ob_end_flush())
		{
			//Void
		}

		/*
		1st query: get all images as they're required for admin area use.
		2nd query: get all category images as they're required for category view.
		3rd & 4th query: get all product images as they're required for product view.
		5th query: get all product images as they're required for category view.
		 */

		$sql = "
		SELECT DISTINCT filename, image_width, image_height FROM
		(
		SELECT i.filename, ('200') AS image_width, ('125') AS image_height
		FROM shop_images AS i

		UNION

		SELECT i.filename, l.category_image_width AS image_width, l.category_image_height AS image_height
		FROM shop_images AS i
		INNER JOIN shop_categories AS c ON i.image_id=c.category_image_id
		INNER JOIN shop_category_layout AS l ON c.category_layout_id=l.category_layout_id

		UNION

		SELECT i.filename, l.product_image_width AS image_width, l.product_image_height AS image_height
		FROM shop_images AS i
		INNER JOIN shop_products AS p ON i.image_id=p.product_image_id
		INNER JOIN shop_product_layout AS l ON p.product_layout_id=l.product_layout_id

		UNION

		SELECT i.filename, l.extra_image_width AS image_width, l.extra_image_height AS image_height
		FROM shop_images AS i
		INNER JOIN shop_products AS p ON i.image_id=p.product_image_id
		INNER JOIN shop_product_layout AS l ON p.product_layout_id=l.product_layout_id

		UNION

		SELECT i.filename, l.product_image_width AS image_width, l.product_image_height AS image_height
		FROM shop_images AS i
		INNER JOIN shop_products AS p ON i.product_id=p.product_id
		INNER JOIN shop_categories_products AS cp ON p.product_id=cp.product_id
		INNER JOIN shop_categories AS c ON cp.category_id=c.category_id
		INNER JOIN shop_category_layout AS l ON c.category_layout_id=l.category_layout_id
		) AS my_query
		";

		$query = $this->db->query($sql);

		//clean out the existing image cache (optional)
		// $files = glob(ABSOLUTE_PATH . '/images/shop/resized/*');
		// foreach($files as $file)
		// {
		// 	set_time_limit(2);

		// 	if(is_file($file))
		// 	{
		// 		unlink($file);
		// 	}
		// }

		//make sure we have an index.html file in here
		touch(ABSOLUTE_PATH . "/images/shop/resized/index.html");

		foreach($query->result() as $row)
		{
			process_thumbnails(array($row->filename), $row->image_width, $row->image_height);
		}
	}

	/* layout specific data functions */
	public function layout_specific_data_list()
	{
		if(!$this->current_user->has(ACTION_SHOP_DATA))
		{
			return $this->denied($this->data);
		}

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/data_list", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function layout_specific_data($layout_specific_data_id=null)
	{
		if(!$this->current_user->has(ACTION_SHOP_DATA))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_layout_specific_data", "shop/shop_product_layout"));

		$id = ($layout_specific_data_id ? $layout_specific_data_id : get_id());

		$layout_specific_data = new Shop_Layout_Specific_Data();
		$layout_specific_data->Load($id);

		$layouts = $this->shop_product_layout->get();

		$this->data["id"] = $id;
		$this->data["layout_specific_data"] = $layout_specific_data;
		$this->data["layouts"] = $layouts;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/data_edit", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function layout_specific_data_save()
	{
		if(!$this->current_user->has(ACTION_SHOP_DATA))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_layout_specific_data");

		$layout_specific_data_id = $this->input->post("layout_specific_data_id");

		$layout_specific_data = new Shop_Layout_Specific_Data();
		$layout_specific_data->Load($layout_specific_data_id);
		$layout_specific_data->readPostVars();

		if($layout_specific_data->key == "")
		{
			$layout_specific_data->key = "custom_" . time();
		}

		if($layout_specific_data->save())
		{
			$this->cache->clean();
			$this->messages[] = "Layout Specific Data Field Saved";
		}
		else
		{
			$this->errors[] = "Error Saving Layout Specific Data Field";
		}

		if($this->input->post("submit_action") == "continue")
		{
			$this->layout_specific_data($layout_specific_data->layout_specific_data_id);
		}
		else
		{
			$this->layout_specific_data_list();
		}
	}

	public function layout_specific_data_delete()
	{
		if(!$this->current_user->has(ACTION_SHOP_DATA))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_layout_specific_data");

		$id = get_id();

		if($id)
		{
			$obj = new Shop_Layout_Specific_Data();
			$obj->load($id);

			if($obj->delete())
			{
				$this->messages[] = "Layout Specific Data Field Deleted";
			}
			else
			{
				$this->errors[] = "Error Deleting Layout Specific Data Field";
			}
		}

		$this->layout_specific_data_list();
	}
	/* end layout specific data functions */

	/* shopper group functions */
	public function shopper_groups()
	{
		if(!$this->current_user->has(ACTION_SHOP_SHOPPER_GROUPS))
		{
			return $this->denied($this->data);
		}

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/shopper_groups", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function shopper_group($id=null)
	{
		if(!$this->current_user->has(ACTION_SHOP_SHOPPER_GROUPS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_shopper_group");

		$shopper_group = new Shop_Shopper_Group();
		$shopper_group->Load($id);

		$this->data["id"] 				= $id;
		$this->data["shopper_group"] 	= $shopper_group;
		$this->data["sites"] 			= $this->sites;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/shopper_group", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function shopper_group_save()
	{
		if(!$this->current_user->has(ACTION_SHOP_SHOPPER_GROUPS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_shopper_group");

		$shopper_group_id = $this->input->post("shopper_group_id");

		$shopper_group = new Shop_Shopper_Group();
		$shopper_group->Load($shopper_group_id);
		$shopper_group->ReadPostVars();

		if($shopper_group->save())
		{
			$this->cache->clean();
			$this->messages[] = "Shopper Group Saved";
		}
		else
		{
			$this->errors[] = "Error Saving Shopper Group";
		}

		if($this->input->post("submit_action") == "continue")
		{
			$this->shopper_group($shopper_group->shopper_group_id);
		}
		else
		{
			$this->shopper_groups();
		}
	}

	public function shopper_group_delete($id=null)
	{
		if(!$this->current_user->has(ACTION_SHOP_SHOPPER_GROUPS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_shopper_group");

		if($id)
		{
			$obj = new Shop_Shopper_Group();
			$obj->load($id);

			if($obj->delete())
			{
				$this->messages[] = "Shopper Group Deleted";
			}
			else
			{
				$this->errors[] = "Error Deleting Shopper Group";
			}
		}

		$this->shopper_groups();
	}
	/* end shopper group functions */

	public function vehicle_link_delete()
	{
		if(!$this->current_user->has(ACTION_SHOP_PRODUCTS))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_vehicle");
		$this->load->helper("url");

		$this->shop_vehicle->delete_link($this->input->get("vehicle_id"), $this->input->get("product_id"));

		redirect("/shop_admin/product?id=" . $this->input->get("product_id") . "&default_tab=4");
	}

	public function build_routes()
	{
		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model(array("shop/shop_category", "shop/shop_product", "shop/shop_route"));
		$this->db->query("TRUNCATE TABLE `shop_routes`");
		$categories = $this->shop_category->LoadAllBare();

		foreach($categories as $category)
		{
			$c = new Shop_Category();
			$c->load($category->category_id);

			$this->shop_route->build_category_route($c);
			unset($c);
		}
		unset($categories);

		$products = $this->shop_product->LoadAllBare();

		foreach($products as $product)
		{
			$p = new Shop_Product();
			$p->load($product->product_id);

			$this->shop_route->build_product_route($p);
			unset($p);
		}

		$this->messages[] = 'Shop routes were rebuilt. You should also <a href="/crawler/sitemap/1">regenerate your sitemap</a>.';
		$this->index();
	}

	/**
	 * Download the postal codes SQL file from files.nerivon.com, extract it, and run the queries.
	 * This function takes a LONG TIME to run since there are nearly 1 million queries in the file.
	 */
	public function install_postalcodes()
	{
		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		// This is going to require significant memory
    	ini_set("memory_limit", "256M");

    	// Download the postal codes file to a temp directory.
		$ch = curl_init("https://files.nerivon.com/shop_postalcodes.sql");
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		$postalcodes = curl_exec($ch);
		curl_close($ch);

		@unlink("/tmp/shop_postalcodes.sql");
		file_put_contents("/tmp/shop_postalcodes.sql", $postalcodes);
		unset($postalcodes);

		if(file_exists("/tmp/shop_postalcodes.sql"))
		{
			// Extract the ZIP file.
			// try
			// {
			// 	$phar = new PharData("/tmp/shop_postalcodes.zip", 0, "shop_postalcode.zip", Phar::ZIP);
			// 	$phar->extractTo('/tmp', "shop_postalcodes.sql", true);
	    	// }
	    	// catch(Exception $e)
	    	// {
	    	// 	$this->errors[] = "Could not extract postal codes: $e";
	    	// 	$this->index();
	    	// 	return;
	    	// }
	    }
	    else
    	{
    		$this->errors[] = "Could not download postal codes";
    		$this->index();
    		return;
    	}

    	$this->db->trans_off();

    	$sql = file_get_contents("/tmp/shop_postalcodes.sql");

    	mysqli_multi_query($this->db->conn_id, $sql);
		while ($this->db->conn_id->more_results()) { $this->db->conn_id->next_result(); } // flush multi_queries

    	// Close the file and delete the temp files.
	    @unlink("/tmp/shop_postalcodes.sql");
	    @unlink("/tmp/shop_postalcodes.zip");

		$this->messages[] = "Postal Codes Installed";
		$this->index();
	}

	public function purge_images()
	{
		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		set_time_limit(120);

		// Any image which is not linked to from a product or category and is not a
		// product "extra image" is no longer in use and can be safely purged.
		$sql = "SELECT DISTINCT image_id FROM shop_images WHERE image_id NOT IN
				(SELECT i.image_id
					FROM shop_products AS p
					INNER JOIN shop_images AS i ON i.image_id=p.product_image_id

					UNION

					SELECT i.image_id
					FROM shop_categories AS c
					INNER JOIN shop_images AS i ON i.image_id=c.category_image_id

					UNION

					SELECT i.image_id
					FROM shop_images AS i
					INNER JOIN shop_products AS p ON i.product_id=p.product_id
				)";

		$query = $this->db->query($sql);

		foreach($query->result() as $row)
		{
			set_time_limit(10);
			$this->db->query("DELETE FROM `shop_images` WHERE `image_id`='" . $row->image_id . "'");
		}

		// Loop all images in our database and "touch" the files.
		// We'll then scan the directory and delete any files that were not touched.
		// This is the only possible way to efficiently process so many images.
		$query = $this->db->query("SELECT filename FROM shop_images");
		$touch_time = time();	// Make sure all touches have the same time for checking later.

		foreach($query->result() as $row)
		{
			touch(ABSOLUTE_PATH . "/images/shop/" . $row->filename, $touch_time);
		}

		$images = scandir(ABSOLUTE_PATH . "/images/shop");

		foreach($images as $image)
		{
			set_time_limit(10);
			$path = ABSOLUTE_PATH . "/images/shop/" . $image;

			if(preg_match('/\.(jpe?g|png|gif|webp)$/i', $image) && preg_match('/@2x/', $image) == false)
			{
				if(filemtime($path) != $touch_time)
				{
					$retina = preg_replace('/\.(jpe?g|png|gif|webp)$/i', '@2x.$1', $path);
					unlink($path);
					@unlink($retina);

					$base = substr($image, 0, strrpos($image, "."));
					$thumbs = glob(ABSOLUTE_PATH . "/images/shop/resized/" . $base . "*");

					foreach($thumbs as $thumb)
					{
						$retina = preg_replace('/\.(jpe?g|png|gif|webp)$/i', '@2x.$1', $path);
						unlink($path);
						@unlink($retina);
					}
				}
			}
		}

		$this->messages[] = "Unused shop images were purged.";
		$this->index();
	}

	/* gateway functions */
	public function gateways()
	{
		$this->init();

		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/gateways", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function payment_gateway($id)
	{
		$this->init();

		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_payment_gateway");

		$gateway = new Shop_payment_gateway();
		$gateway->load($id);
		$this->data["id"] 		= $id;
		$this->data["gateway"] 	= $gateway;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/payment_gateway", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function payment_gateway_save()
	{
		$this->init();

		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_payment_gateway");

		$gateway = new Shop_payment_gateway();
		$gateway->load($this->input->post("id"));
		$gateway->enabled = ($this->input->post("enabled") ? 1 : 0);
		$gateway->sort = $this->input->post("sort");

		$configs = explode("\n", $gateway->configuration);
		$gateway->configuration = "";

		foreach($configs as $config)
		{
			if($config != "")
			{
				$line = explode("=", $config, 2);

				$gateway->configuration .= $line[0] . "=" . $this->input->post("config_" . $line[0]) . "\n";
			}
		}

		if($gateway->save())
		{
			$this->cache->clean();
			$this->messages[] = "Payment Gateway Saved";

			if($this->input->post("submit_action") == "continue")
			{
				$this->payment_gateway($gateway->payment_gateway_id);
			}
			else
			{
				$this->gateways();
			}
		}
		else
		{
			$this->errors[] = "Error Saving Payment Gateway";
			$this->payment_gateway($gateway->payment_gateway_id);
		}
	}

	public function shipping_gateway($id)
	{
		$this->init();

		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_shipping_gateway");

		$gateway = new Shop_shipping_gateway();
		$gateway->load($id);
		$this->data["id"] 		= $id;
		$this->data["gateway"] 	= $gateway;

		$this->load->view("common/header", $this->data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		$this->load->view("shop/shipping_gateway", $this->data);
		$this->load->view("common/footer", $this->data);
	}

	public function shipping_gateway_save()
	{
		$this->init();

		if(!$this->current_user->has(ACTION_SHOP_CONFIG))
		{
			return $this->denied($this->data);
		}

		$this->load->model("shop/shop_shipping_gateway");

		$gateway = new Shop_shipping_gateway();
		$gateway->load($this->input->post("id"));
		$gateway->enabled = ($this->input->post("enabled") ? 1 : 0);
		$gateway->sort = $this->input->post("sort");

		$configs = explode("\n", $gateway->configuration);
		$gateway->configuration = "";

		foreach($configs as $config)
		{
			if($config != "")
			{
				$line = explode("=", $config, 2);

				$gateway->configuration .= $line[0] . "=" . $this->input->post("config_" . $line[0]) . "\n";
			}
		}

		if($gateway->save())
		{
			$this->cache->clean();
			$this->messages[] = "Shipping Gateway Saved";

			if($this->input->post("submit_action") == "continue")
			{
				$this->shipping_gateway($gateway->shipping_gateway_id);
			}
			else
			{
				$this->gateways();
			}
		}
		else
		{
			$this->errors[] = "Error Saving Shipping Gateway";
			$this->shipping_gateway($gateway->shipping_gateway_id);
		}
	}
	/* end of gateway functions */
}
