<?php

/**
 * This is a common Component which will be used accross all Module-Controllers
 *
 * PHP version 5.6
 *
 * @category  Component
 * @package   Slim
 * @author    Tanmaya Patra <tanmayap@riaxe.com>
 * @copyright 2019-2020 Riaxe Systems
 * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
 * @link      http://inkxe-v10.inkxe.io/xetool/admin
 */

namespace App\Components\Controllers;

use App\Components\Models\AssetType as AssetType;
use App\Components\Models\Category as Category;
use App\Components\Models\EmailLog as EmailLog;
use App\Components\Models\ProductionAbbriviations as ProductionAbbriviations;
use App\Components\Models\ProductionEmailTemplates as ProductionEmailTemplates;
use App\Components\Models\ProductionHubModule as ProductionHubModule;
use App\Components\Models\ProductionHubSetting as ProductionHubSetting;
use App\Components\Models\ProductionStatus as ProductionStatus;
use App\Components\Models\ProductionTags as ProductionTags;
use App\Components\Models\PurchaseOrderStatus as PurchaseOrderStatus;
use App\Components\Models\QuotationPaymentMethods as QuotationPaymentMethods;
use App\Components\Models\QuotationPaymentSettings as QuotationPaymentSettings;
use App\Components\Models\StatusAssigneeRel as StatusAssigneeRel;
use App\Components\Models\StatusFeatures as StatusFeatures;
use App\Components\Models\StatusPrintProfileRel as StatusPrintProfileRel;
use App\Components\Models\Tag as Tag;
use App\Dependencies\Zipper as Zipper;
use App\Modules\Cliparts\Models\Clipart;
use App\Modules\Fonts\Models\Font;
use App\Modules\PrintProfiles\Models as PrintProfileModels;
use App\Modules\Settings\Models\Language;
use Illuminate\Database\Capsule\Manager as DB;
use ProductStoreSpace\Controllers\StoreProductsController;
use App\Components\Models\ProductionJobHolidays;
use App\Modules\Images\Models\BrowserImages;
use App\Modules\Images\Models\UserImage;
use App\Modules\Customers\Controllers\CustomerGroupController as CustomerGroup;
use App\Modules\Integration\Models\PluginSettings;
use App\Modules\Integration\Controllers\QuickBookController;
use App\Modules\Orders\Controllers\OrdersController;
use App\Modules\BarCode\Models\Barcodes;



/**
 * Surpress PHPMD Errors
 *
 * @SuppressWarnings(PHPMD)
 */

/**
 * Component Class
 *
 * @category Component
 * @package  Slim
 * @author   Tanmaya Patra <tanmayap@riaxe.com>
 * @license  http://www.gnu.org/copyleft/gpl.html GNU General Public License
 * @link     http://inkxe-v10.inkxe.io/xetool/admin
 */
class Component
{

	private $s3Settings = [];

	/**
	 * Initialize Constructor
	 */
	public function __construct()
	{
		// Default store id declared as 1 as timezone set not done for multi store. 
		$defautStoreId = 1;
		$settngs = $this->readSettingJsonFile($defautStoreId);
		if (isset($settngs['timezone'])) {
			date_default_timezone_set($settngs['timezone']);
		}
	}

	/**
	 * Get the color swatches from inkxe database
	 *
	 * @param $colorDetail Color Details
	 *
	 * @author satyabratap@riaxe.com
	 * @date   23 Jan 2019
	 * @return Array
	 */
	public function getColorSwatchData($colorDetail, $combineData = [])
	{
		// Note: while hex_code and file - priority given to imprintnext(1st), then store
		// the central server color swatch has to merge first with the imprintnext DB(one time)
		// calling to central server for colorswatch made it slow
		$variantData = [];
		if (!empty($colorDetail)) {
			// shopify: attribute_id (is color) converted to lowercase
			if (STORE_NAME == 'Shopify') {
				array_walk($colorDetail, function (&$colDet) {
					$colDet['id'] = str_replace(' ', '_', strtolower($colDet['id']));
				});
			}
			$colorSwatchInit = new \App\Modules\Settings\Models\ColorSwatch();
			// get all term ids
			$allTermIds = array_column($colorDetail, 'id');

			// get all the swatches for imprintnext (priority-1)
			$getTermLocalData = $colorSwatchInit->whereIn('attribute_id', $allTermIds)->get();
			// merge the local color swatches
			if ($getTermLocalData->count()) {
				foreach ($getTermLocalData as $getTermLocal) {
					$allTermKey = array_search(strtolower($getTermLocal->attribute_id), $allTermIds);
					if ($allTermKey !== false) {
						if (!empty($getTermLocal->file_name) && $getTermLocal->cloud_storage == 1) {
							$thisFilename = $this->getS3URL('/assets/swatches/' . $getTermLocal->file_name, 1);
						} elseif (!empty($getTermLocal->file_name) && $getTermLocal->cloud_storage != 1) {
							$thisFilename = path('read', 'swatch') . $getTermLocal->file_name;
						} else {
							$thisFilename = "";
						}
						$colorDetail[$allTermKey]['xe_id'] = $getTermLocal->xe_id;
						$colorDetail[$allTermKey]['file_name'] =  $thisFilename;
						$colorDetail[$allTermKey]['hex_code'] = empty($colorDetail['attrbitue_name']) ? $getTermLocal->hex_code : '';
						$colorDetail[$allTermKey]['color_type'] = $getTermLocal->color_type;
					}
				}
			}
			// devide the terms based on blank & color/hex code
			$groupedTerms = array_reduce(
				$colorDetail,
				function ($accumulator, $termValue) {
					if (empty($termValue['file_name']) && empty($termValue['hex_code'])) {
						$accumulator['blank'][] = $termValue;
					} else {
						$accumulator['color'][] = $termValue;
					}
					return $accumulator;
				},
				[
					'blank' => [],
					'color' => []
				]
			);
			if (!empty($groupedTerms['blank'])) {
				// create new swatches or request to central to create
				$newAddedColor = $this->updateClientColorSwatch($groupedTerms['blank']);
				// merge new color swatches
				$colorDetail = array_merge($newAddedColor, $groupedTerms['color']);
			}
			foreach ($colorDetail as $colorDet) {
				$variantData[] = [
					'id' => (!empty($colorDet['xe_id'])) ? $colorDet['xe_id'] : $colorDet['id'],
					'attribute_id' => $colorDet['id'],
					'name' => $colorDet['name'],
					'hex_code' => isset($colorDet['hex_code']) ? $colorDet['hex_code'] : "",
					'file_name' => isset($colorDet['file_name']) ? $colorDet['file_name'] : "",
					'color_type' => isset($colorDet['color_type']) ? $colorDet['color_type'] : "",
					'variant_id' => $colorDet['variant_id'],
					'inventory' => $colorDet['inventory'],
					'attribute' => isset($colorDet['attribute']) ? $colorDet['attribute'] : [],
					'price' => $colorDet['price'],
					'tax' => $colorDet['tax'],
					'sides' => $colorDet['sides'],
					'tier_prices' => isset($colorDet['tier_prices']) ? $colorDet['tier_prices'] : []
				];
			}
		}
		return $variantData;
	}
	/**
	 * Update the ImprintNext color from the central server for the blank colors
	 */
	public function updateClientColorSwatch($missingColors)
	{
		// requested attribute ids stored in the file(temp) as ignore list for the central server color swatch
		// it will minimize the hit to the central server for requesting missing color swatch
		$requestStackDir = ASSETS_PATH_W . 'color_swatch_req/';
		create_directory($requestStackDir);
		$requestStackFile = $requestStackDir . 'missing_color.json';
		// get the previously requestde attribute ids
		$getPreviousRequested = @file_get_contents($requestStackFile);
		$prevRequestedIds = array_filter(explode(',', $getPreviousRequested));
		$missingColorAttrIds = array_column($missingColors, 'id');
		// do not continue if get request for color from central is already done for the attribute_id
		$newRequestedIds = array_diff($missingColorAttrIds, $prevRequestedIds);
		if (empty($newRequestedIds)) {
			return $missingColors;
		}
		// Read the global color swatch data
		$filePath = COLOR_SWATCH_JSON_URL;
		$data = fileGetContentsCurl($filePath);
		$colorData = json_decode($data, true);
		// convert all color key to lowercase
		if (is_array($colorData)) {
			$colorData = array_change_key_case($colorData, CASE_LOWER);
		}
		$resultAddedSwatches = [];
		foreach ($missingColors as $missingColor) {
			$newRequestedIdIndex = array_search($missingColor['id'], $newRequestedIds);
			if ($newRequestedIdIndex === false || !isset($colorData[strtolower($missingColor['name'])])) {
				// add to return list - color not found in centra server result, also added to ignore list
				$resultAddedSwatches[] = $missingColor;
				continue;
			}
			// check if the color present on the central server json
			$hexCode  = $colorData[strtolower($missingColor['name'])];
			$colorSwatchData = [
				'attribute_id' => $missingColor['id'],
				'hex_code' => $hexCode,
				'file_name' => '',
				'color_type' => $this->colorStrength($hexCode)
			];
			// add the color to the imprintnext color swatch
			$colorSwatchObj = new \App\Modules\Settings\Models\ColorSwatch($colorSwatchData);
			if ($colorSwatchObj->save()) {
				$resultAddedSwatches[] = array_merge($missingColor, $colorSwatchObj->toArray());
			}
			// remove from ignore list for central server
			unset($newRequestedIds[$newRequestedIdIndex]);
		}

		// update ignore attribute id list
		$updatedList = array_merge($prevRequestedIds, $newRequestedIds);

		// update the ignore list from the color swatch table
		$findExising = (new \App\Modules\Settings\Models\ColorSwatch())->select('attribute_id')
			->whereIn('attribute_id', $updatedList);
		if ($findExising->count()) {
			$getExistingAttributeIds = $findExising->get()->pluck('attribute_id')->toArray();
			$updatedList = array_diff($updatedList, $getExistingAttributeIds);
		}

		file_put_contents($requestStackFile, implode(',', $updatedList));

		return $resultAddedSwatches;
	}

	/**
	 * Get the color strength from the hex code
	 */
	public function colorStrength($color = '#FFFFFF')
	{
		// imprintnext code for color type: dark=5,light=6,white=4
		$coloType = 5;
		// algorithm to detect whether a color light or dark
		$color = ltrim($color, '#');
		$r = hexdec(substr($color, 0, 2));
		$g = hexdec(substr($color, 2, 2));
		$b = hexdec(substr($color, 4, 2));
		$squaredContrast = ($r * $r * .299 +
			$g * $g * .587 +
			$b * $b * .114
		);
		// > 130 is a white color
		if ($squaredContrast > pow(140, 2)) {
			$coloType = 4;
		} elseif ($squaredContrast > pow(60, 2)) {
			$coloType = 6;
		}
		return $coloType;
	}

	/**
	 * Get the attribute name for store use
	 *
	 * @author satyabratap@riaxe.com
	 * @author debasishd@riaxe.com
	 * @date   29 Jan 2020
	 * @return array
	 */
	public function getAttributeName()
	{
		$attributeInit = new \App\Modules\Settings\Models\Setting();
		$getAttributes = $attributeInit->where('type', 4)
			->get();
		$storeAttributes = [];
		if (strtolower(STORE_NAME) == "shopify") {
			$storeAttributes['color'] = "color";
			$storeAttributes['size'] = "size";
		} else {
			if ($getAttributes->count() > 0) {
				foreach ($getAttributes as $value) {
					$storeAttributes[$value['setting_key']] = $value['setting_value'];
				}
			}
		}

		return $storeAttributes;
	}

	/**
	 * As with predefirened PUT parser we were unable to get data and files in
	 * form data. So this custom Parser is used for adding a intermediate Parser
	 * so that we can get the form data
	 *
	 * @author tanmayap@riaxe.com
	 * @date   17 sept 2019
	 * @return All Formdata from Put method
	 */
	public function parsePut()
	{
		$matches = "";
		// PUT data comes in on the stdin stream
		$putdata = fopen("php://input", "r");
		// Open a file for writing
		// $fp = fopen("myputfile.ext", "w");
		$rawData = '';
		// Read the data 1 KB at a time and write to the file
		while ($chunk = fread($putdata, 1024)) {
			$rawData .= $chunk;
		}
		// Close the streams
		fclose($putdata);
		// Fetch content and determine boundary
		$boundary = substr($rawData, 0, strpos($rawData, "\r\n"));
		if (empty($boundary)) {
			parse_str($rawData, $data);
			return $data;
		}
		// Fetch each part
		$parts = array_slice(explode($boundary, $rawData), 1);
		$data = array();
		foreach ($parts as $part) {
			// If this is the last part, break
			if ($part == "--\r\n") {
				break;
			}

			// Separate content from headers
			$part = ltrim($part, "\r\n");
			list($rawHeaders, $body) = explode("\r\n\r\n", $part, 2);
			// Parse the headers list
			$rawHeaders = explode("\r\n", $rawHeaders);
			$headers = array();
			foreach ($rawHeaders as $header) {
				list($name, $value) = explode(':', $header);
				$headers[strtolower($name)] = ltrim($value, ' ');
			}
			// Parse the Content-Disposition to get the field name, etc.
			if (isset($headers['content-disposition'])) {
				$filename = null;
				$tmpName = null;
				preg_match(
					'/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/',
					$headers['content-disposition'],
					$matches
				);

				//Parse File
				if (isset($matches[4])) {
					//if labeled the same as previous, skip
					if (isset($_FILES[$matches[2]])) {
						continue;
					}
					//get filename
					$filename = $matches[4];
					//get tmp name
					$filenameParts = pathinfo($filename);
					$tmpName = tempnam(
						ini_get('upload_tmp_dir'),
						$filenameParts['filename']
					);
					// populate $_FILES with information, size may be off in
					// multibyte situation
					$_FILES[$matches[2]] = array(
						'error' => 0,
						'name' => $filename,
						'tmp_name' => $tmpName,
						'size' => strlen($body),
						'type' => $value,
					);
					//place in temporary directory
					file_put_contents($tmpName, $body);
				} else {
					//Parse Field
					$data[$name] = substr($body, 0, strlen($body) - 2);
				}
			}
		}
		return $data;
	}

	/**
	 * Get Assets Type ID from module slug name
	 *
	 * @param $slug slug name of the asset
	 *
	 * @author tanmayap@riaxe.com
	 * @date   3rd Dec 2019
	 * @return array
	 */
	public function assetsTypeId($slug)
	{
		$assetResponse = [
			'status' => 0,
			'message' => message('Slug', 'not_found'),
		];
		if (!empty($slug)) {
			$assetTypeObj = new AssetType();
			$getAssetType = $assetTypeObj->where('slug', $slug);
			if ($getAssetType->count() > 0) {
				$statement = $getAssetType->first();
				$assetResponse = [
					'status' => 1,
					'asset_type_id' => $statement->xe_id,
				];
			}
		}

		return $assetResponse;
	}

	/**
	 * Get List of all tags according to the Slug-name
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slug value of the individual helper file
	 *
	 * @author tanmayap@riaxe.com
	 * @date   31 Jan 2019
	 * @return Array of categories
	 */
	public function getAssetTags($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 1,
			'data' => [],
			'message' => message('Tags', 'not_found'),
		];
		$tablePerSlug = [
			'cliparts' => 'clipart_tag_rel',
			'backgrounds' => 'background_tag_rel',
			'shapes' => 'shape_tag_rel',
			'color-palettes' => 'color_tag_rel',
			'fonts' => 'font_tag_rel',
			'templates' => 'template_tag_rel',
		];
		$slug = trim($args['slug']);
		$tagList = [];
		if (!empty($tablePerSlug[$slug])) {
			$table = $tablePerSlug[$slug];
			$assetType = DB::table($table)
				->select('xe_id as id', 'name');
			if ($assetType->count() > 0) {
				$tagList = $assetType->leftJoin('tags', $table . '.tag_id', '=', 'tags.xe_id')
					->whereNotNull('name')
					->groupBy($table . '.tag_id')
					->orderBy('name', 'asc')
					->get();
				$jsonResponse = [
					'status' => 1,
					'data' => $tagList,
				];
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Get: Get related Categories by Module's Primary Key ID
	 *
	 * @param $moduleDir The Directory name where the Model is exists
	 * @param $modelName The model name that we use to get relational records
	 * @param $colName   module's foreign key column name
	 * @param $colValue  category's foreign key column name
	 * @param $type      it is a alternate between name and id
	 *
	 * @author tanmayap@riaxe.com
	 * @date   13 Jan 2020
	 * @return array
	 */
	public function getCategoriesById(
		$moduleDir,
		$modelName,
		$colName,
		$colValue,
		$type = 'id'
	) {
		$categoryIdList = [];
		$modelPath = 'App\\Modules\\' . $moduleDir . '\\' . 'Models' . '\\';
		$modelPath .= $modelName;
		$categoryInit = new $modelPath();
		$relTable = $categoryInit->getTable();
		$getCategory = $categoryInit->join('categories', "{$relTable}.category_id", '=', 'categories.xe_id')
			->select('category_id', 'parent_id', 'name')
			->where('categories.is_disable', 0)
			->where($colName, $colValue)
			->get();
		if (!empty($getCategory)) {
			// if name given, parent_id == 0 will be added
			foreach ($getCategory as $category) {
				if ($type == 'id') {
					$categoryIdList[] = $category->category_id;
				}
				if ($type == 'name' && $category->parent_id == 0) {
					$categoryIdList[] = $category->name;
				}
			}
		}
		return $categoryIdList;
	}
	/**
	 * Get: Get related Tags by Module's Primary Key ID
	 *
	 * @param $moduleDir The Directory name where the Model is exists
	 * @param $modelName The model name that we use to get relational records
	 * @param $colName   module's foreign key column name
	 * @param $colValue  tag's foreign key column name
	 *
	 * @author tanmayap@riaxe.com
	 * @date   13 Jan 2020
	 * @return array
	 */
	public function getTagsById($moduleDir, $modelName, $colName, $colValue)
	{
		$tagNames = [];
		// Get Tag names
		$modelPath = 'App\\Modules\\' . $moduleDir . '\\' . 'Models' . '\\';
		$modelPath .= $modelName;
		$tagRelInit = new $modelPath();
		$tagRelTable = $tagRelInit->getTable();
		$getTags = $tagRelInit->join('tags', "{$tagRelTable}.tag_id", '=', 'tags.xe_id')
			->where($colName, $colValue)
			->select(['tags.xe_id', 'tags.name'])
			->groupBy('tags.xe_id', 'tags.name')
			->get()
			->pluck('name')
			->toArray();
		if (!empty($getTags)) {
			$tagNames = $getTags;
		}
		return $tagNames;
	}

	/**
	 * Delete/Trash old file and thumbs(is exists) of a specific Model from its
	 * corsp. Folder
	 *
	 * @param $table        Database Table Name
	 * @param $column       Column in which we can get file name
	 * @param $condition    Condition to get the specific file
	 * @param $folder       Folder from where we will delete the file
	 * @param $newFileCheck Check if old file passes
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return All Print Profile List
	 */
	public function deleteOldFile($table, $column, $condition, $folder, $newFileCheck = true)
	{
		$deleteCount = 0;
		// Delete the file if and only if any file uploaded from api
		// Or, you can disable this by sending false key to $newFileCheck
		$fileCheck = 1;
		if ($newFileCheck === true) {
			$fileCheck = 0;
			if (!empty($_FILES)) {
				$fileCheck = 1;
			}
		}
		// filter column name and table name: allow strict characters
		$safePattern = '/[^a-z0-9_]+/i';
		$table = preg_replace($safePattern, '', $table);
		$column = preg_replace($safePattern, '', $column);

		if (!empty($table) && !empty($column) && $fileCheck === 1) {
			$fields = ["{$column} as file_name"];
			$initTable = new DB();
			$getSelectedRecord = $initTable->table($table);
			if (isset($condition) && count($condition) > 0) {
				$getSelectedRecord->where($condition)->select($fields);
			}

			if ($getSelectedRecord->count() > 0) {
				$getAllFileNames = $getSelectedRecord->get();
				foreach ($getAllFileNames as $getFile) {
					if (isset($getFile->file_name) && $getFile->file_name != "") {
						$rawFileLocation = $folder . $getFile->file_name;
						if (delete_file($rawFileLocation)) {
							$deleteCount++;
							$rawThumbFileLocation = $folder . 'thumb_' .
								$getFile->file_name;
							delete_file($rawThumbFileLocation);
						}
					}
				}
			}
		}

		return $deleteCount > 1 ? true : false;
	}

	/**
	 * Get all Categories in Recursion format from the Database
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author satyabratap@riaxe.com
	 * @date   28 Mar 2020
	 * @return json
	 */
	public function getCategoryByPrintProfile($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'data' => [],
			'message' => message('Category', 'not_found'),
		];
		$storeId = $request->getQueryParam('store_id');
		$customerId = $request->getQueryParam('customer');
		$isS3Enabled = $this->checkS3Settings($storeId);
		$customerGroupControllerInit = new CustomerGroup();
		$customerGroupId = $customerGroupControllerInit->getGroupIdBycustomerId($customerId, $storeId);
		//$printProfileId = to_int($args['id']);
		if (!empty($args)) {
			$printProfileId = to_int($args['id']);
			$moduleSlugName = trim($args['slug']);
			//GET MEMCACHEDATA
			$memcacheData = [];
			if (IS_MEMCACHE && !empty($printProfileId) && !empty($args)) {
				//MEMCACHED KEY
				$thisCacheKey = $moduleSlugName . "_cat_pp" . $printProfileId . "_s" . $storeId;
				//Register MEMCACHED KEY in Local Cache
				$this->createUpdateMemCacheGroup($moduleSlugName . '_cat', $thisCacheKey, 'SET');
				$memcacheData = $this->memcache("get", $thisCacheKey);
			}
			$assetCacheData = [];
			$assetCacheData = $this->getAssetCatCache($storeId, $printProfileId, $moduleSlugName);
		} else {
			$printProfileId = $request->getQueryParam('print_profile_id');
			$moduleSlugName = $request->getQueryParam('asset_slug');
		}
		if (empty($memcacheData)) {
			if (empty($assetCacheData)) {
				//if (!empty($args['slug'])) {
				//$moduleSlugName = trim($args['slug']);
				// Getting Assets module id
				$assetTypeArr = $this->assetsTypeId($moduleSlugName);
				$assetTypeId = $assetTypeArr['asset_type_id'];
				$catIds = $customerGroupControllerInit->getAssetsBygroupId($customerGroupId, $assetTypeId, $storeId);
				if (!empty($assetTypeArr) && $assetTypeArr['status'] == 1) {
					$assetTypeId = $assetTypeArr['asset_type_id'];
					if (isset($printProfileId) && $printProfileId > 0) {
						$profileCatRelObj = new \App\Modules\PrintProfiles\Models\PrintProfileAssetsCategoryRel();
						$profileCatRelDetails = $profileCatRelObj->where(
							[
								'asset_type_id' => $assetTypeId,
								'print_profile_id' => $printProfileId,
							]
						)
							->get();

						foreach ($profileCatRelDetails->toArray() as $key => $value) {
							$categoryInit = new Category();
							$getCategories = $categoryInit->select(
								'xe_id as id',
								'parent_id',
								'name',
								'file_name',
								'sort_order',
								'is_disable',
								'is_default',
								'cloud_storage',
								'asset_available_flag'
							)
								->where(
									[
										'parent_id' => 0,
										'asset_type_id' => $assetTypeId,
										'xe_id' => $value['category_id'],
									]

								);
							if (!empty($catIds)) {
								$getCategories = $getCategories->whereIn('xe_id', $catIds);
							}
							$getCategories = $getCategories->orderBy('sort_order', 'asc');
							$getCategories = $getCategories->get()->toArray();
							foreach ($getCategories as $categories) {
								if (!empty($categories['file_name'])) {
									if ($isS3Enabled || $categories['cloud_storage'] == 1) {
										$file = CATEGORY_FOLDER . 'thumb_' . $categories['file_name'];
										$categories['file_name'] = $this->getS3URL($file, $storeId);
									} else {
										$categories['file_name'] = CATEGORY_FOLDER_R . 'thumb_' . $categories['file_name'];
									}
								} else {
									$categories['file_name'] = "";
								}
							}
							if (!empty($getCategories[0]) && $getCategories[0]['asset_available_flag'] == 1) {
								//echo array_search(1,$catIds);					
								$parentDetails[$key]['id'] = $getCategories[0]['id'];
								$parentDetails[$key]['name'] = $getCategories[0]['name'];
								$parentDetails[$key]['image_path'] = !empty($categories['file_name']) ? $categories['file_name'] : '';
								$parentDetails[$key]['order'] = $getCategories[0]['sort_order'];
								$parentDetails[$key]['is_disable'] = $getCategories[0]['is_disable'];
								$parentDetails[$key]['is_default'] = $getCategories[0]['is_default'];

								$subCategoryInit = new Category();
								$getSubCategories = $subCategoryInit->select(
									'xe_id as id',
									'parent_id',
									'name',
									'file_name',
									'sort_order',
									'is_disable',
									'is_default',
									'cloud_storage',
									'asset_available_flag',
									'asset_type_id'
								)
									->where(
										[
											'parent_id' => $getCategories[0]['id'],
											'asset_available_flag' => 1,
										]
									)
									->orderBy('sort_order', 'asc')
									->get()->toArray();
								$childDetails = [];
								if (!empty($getSubCategories)) {
									foreach ($getSubCategories as $childKey => $childValue) {
										if (!empty($childValue['file_name'])) {
											if ($isS3Enabled && $childValue['cloud_storage'] == 1) {
												$file = CATEGORY_FOLDER . 'thumb_' . $childValue['file_name'];
												$childValue['file_name'] = $this->getS3URL($file, $storeId);
											} else {
												$childValue['file_name'] = CATEGORY_FOLDER_R . 'thumb_' . $childValue['file_name'];
											}
										} else {
											$childValue['file_name'] = "";
										}
										$childDetails[$childKey]['id'] = $childValue['id'];
										$childDetails[$childKey]['name'] = $childValue['name'];
										$childDetails[$childKey]['image_path'] = !empty($childValue['file_name']) ? $childValue['file_name'] : '';
										$childDetails[$childKey]['order'] = $childValue['sort_order'];
										$childDetails[$childKey]['is_disable'] = $childValue['is_disable'];
										$childDetails[$childKey]['is_default'] = $childValue['is_default'];
										$getSelectedStatus = $this->checkCategorySelected($printProfileId, $childValue['asset_type_id'], $childValue['id']);
										$childDetails[$childKey]['is_selected'] = to_int($getSelectedStatus);
									}
								}
								$parentDetails[$key]['subs'] = $childDetails;
							}
						}
					}
				}
				//}
				if (is_array($parentDetails) && !empty($parentDetails)) {
					$keys = array_column($parentDetails, 'order');
					array_multisort($keys, SORT_ASC, $parentDetails);
					$jsonResponse = [
						'status' => 1,
						'data' => array_values($parentDetails),
					];
				}
			} else {
				$jsonResponse = [
					'status' => 1,
					'data' => $assetCacheData['data'],
				];
			}
			//SET IN MEMCACHED
			if (IS_MEMCACHE && isset($thisCacheKey)) {
				$this->memcache("set", $thisCacheKey, $jsonResponse);
			}
		} else {
			$jsonResponse = $memcacheData;
			if (MEM_MODE) {
				$jsonResponse['mode'] = 'memcache';
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/*
		     *---------------------------------------------------------------
		     * Common Category Operations
		     *---------------------------------------------------------------
		     *
		     * All Category CRUD Operations are handled by these common functions.
		     * We can access to these common methods from any individual routes .
	*/
	/**
	 * Get all Categories in Recursion format from the Database
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function getCategories($request, $response, $args)
	{

		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 1,
			'data' => [],
			'message' => message('Category', 'not_found')
		];
		$categoryId = to_int($args['id']);
		$storeDetails = get_store_details($request);
		$storeId = $storeDetails['store_id'] ? $storeDetails['store_id'] : 1;
		$page = $request->getQueryParam('page');
		$perpage = $request->getQueryParam('perpage');
		if (!empty($args['slug'])) {
			$moduleSlugName = trim($args['slug']);
			// Getting Assets module id
			$assetTypeArr = $this->assetsTypeId($moduleSlugName);
			if (!empty($assetTypeArr) && $assetTypeArr['status'] == 1) {
				$categoryInit = new Category();
				$printProfRelInit = new \App\Modules\PrintProfiles\Models\PrintProfileAssetsCategoryRel();

				$assetTypeId = $assetTypeArr['asset_type_id'];
				$getCategories = $categoryInit->select([
					'xe_id as id',
					'parent_id',
					'name',
					'file_name',
					'sort_order',
					'is_disable',
					'is_default',
					'is_defined',
					'cloud_storage'
				])->where([
					'parent_id' => 0,
					'asset_type_id' => $assetTypeId,
					'store_id' => $storeId
				]);
				if (isset($categoryId) && $categoryId > 0) {
					$getCategories->where('xe_id', $categoryId);
				}
				$totalRecords = $getCategories->count();
				if ($page != "") {
					$totalItem = empty($perpage) ? 10 : $perpage;
					$offset = $totalItem * ($page - 1);
					$getCategories->skip($offset)->take($totalItem);
				}
				if ($totalRecords > 0) {
					$getCategories = $getCategories->get()->toArray();
					$categoryDetails = [];
					foreach ($getCategories as $value) {
						$printProfileCount = $printProfRelInit->where(['category_id' => $value['id'], 'asset_type_id' => $assetTypeId])->count();
						$imagePath = '';
						if (!empty($value['file_name'])) {
							if ($value['cloud_storage'] == 1) {
								$file = CATEGORY_FOLDER . 'thumb_' . $value['file_name'];
								$imagePath = $this->getS3URL($file, $storeId);
							} else {
								$imagePath = CATEGORY_FOLDER_R . 'thumb_' . $value['file_name'];
							}
						}
						$categoryDetails[] = [
							'id' => $value['id'],
							'name' => $value['name'],
							'image_path' => $imagePath,
							'order' => $value['sort_order'],
							'is_disable' => $value['is_disable'],
							'is_default' => $value['is_default'],
							'is_defined' => $value['is_defined'],
							'print_profile_count' => $printProfileCount,
							'subs' => $this->getSubCatetgories($storeId, $value['id'], $assetTypeId),
						];
					}
					$jsonResponse = [
						'status' => 1,
						'data' => $categoryDetails,
						'total_records' => $totalRecords,
						'records' => count($categoryDetails)
					];
				}
			}
		}
		return response($response, [
			'data' => $jsonResponse,
			'status' => $serverStatusCode
		]);
	}

	/**
	 * Getting subcategory recurssively
	 *
	 * @param $parentCategoryId Parent Category ID
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return array
	 */
	protected function getSubCatetgories($storeId, $parentCategoryId, $assetTypeId)
	{
		$subcategory = [];
		$categoryInit = new Category();

		$getCategories = $categoryInit->select([
			'xe_id as id',
			'parent_id',
			'name',
			'file_name',
			'sort_order',
			'is_disable',
			'is_default',
			'cloud_storage'
		])
			->where(['parent_id' => $parentCategoryId]);

		if ($getCategories->count() > 0) {
			$printProfRelInit = new \App\Modules\PrintProfiles\Models\PrintProfileAssetsCategoryRel();
			$getCategoriesList = $getCategories->orderBy('sort_order', 'asc')->get()->toArray();
			foreach ($getCategoriesList as $value) {
				$subCatList = [];
				$fetchCount = $categoryInit->select('xe_id')->where(['parent_id' => $value['id']])->count();
				if ($fetchCount > 0) {
					$subCatList = $this->getSubCatetgories($storeId, $value['id']);
				}
				$printProfCount = $printProfRelInit->where(['category_id' => $value['id'], 'asset_type_id' => $assetTypeId])->count();
				$imagePath = '';
				if (!empty($value['file_name'])) {
					if ($value['cloud_storage'] == 1) {
						$file = CATEGORY_FOLDER . 'thumb_' . $value['file_name'];
						$imagePath = $this->getS3URL($file, $storeId);
					} else {
						$imagePath = CATEGORY_FOLDER_R . 'thumb_' . $value['file_name'];
					}
				}
				$subcategory[] = [
					'id' => $value['id'],
					'name' => $value['name'],
					'image_path' => $imagePath,
					'order' => $value['sort_order'],
					'parent_id' => $value['parent_id'],
					'is_disable' => $value['is_disable'],
					'is_default' => $value['is_default'],
					'print_profile_count' => $printProfCount,
					'subs' => $subCatList
				];
			}
		}

		return $subcategory;
	}
	/**
	 * Post: Save category details according to slug
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function saveCategory($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Category', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$storeDetails = get_store_details($request);
		$storeId = $storeDetails['store_id'] ? $storeDetails['store_id'] : 1;
		$isS3Enabled = $this->checkS3Settings($storeId);
		$cloudStorage = 0;
		if (!is_dir(CATEGORY_FOLDER)) {
			mkdir(CATEGORY_FOLDER, 0755);
		}
		$imageFileSize = $_FILES['image_file']['size'];
		//checking file size
		if ($imageFileSize > FILE_SIZE) {
			$jsonResponse = [
				'status' => 0,
				'message' => 'Sorry, your file is too large',
			];
		} else {
			$categoryImage = do_upload('image_file', CATEGORY_FOLDER, [100], 'string');
			if ($isS3Enabled) {
				$cloudStorage = 1;
				$fileToUpload = !empty($categoryImage) ? CATEGORY_FOLDER . 'thumb_' . $categoryImage : '';
				!empty($fileToUpload) ? $this->uploadFileToS3("categories", $fileToUpload, $storeId) : '';
			}
			$allPostPutVars['file_name'] = $categoryImage;
			$allPostPutVars['cloud_storage'] = $cloudStorage;
			$allPostPutVars['asset_available_flag'] = 0;
			$originalFile = CATEGORY_FOLDER . $allPostPutVars['file_name'];
			$thumbFile = CATEGORY_FOLDER . 'thumb_' . $allPostPutVars['file_name'];
			//deleting original image file
			if (isset($thumbFile)) {
				unlink($originalFile);
			}
			if (!empty($args['slug'])) {
				// Getting assets module id
				$assetTypeArr = $this->assetsTypeId($args['slug']);
				$getCategoryInit = new Category();
				$getCategoryDetails = $getCategoryInit->where(
					[
						'name' => $allPostPutVars['name'],
						'asset_type_id' => $assetTypeArr['asset_type_id'],
						'parent_id' => $allPostPutVars['parent_id'],
						'store_id' => $storeId,
					]
				);
				if ($getCategoryDetails->count() > 0) {
					$jsonResponse = [
						'status' => 0,
						'message' => 'The name is already exist',
					];
				} else {
					if (!empty($assetTypeArr) && $assetTypeArr['status'] == 1) {
						$allPostPutVars['asset_type_id'] = $assetTypeArr['asset_type_id'];
						if (!isset($allPostPutVars['sort_order'])) {
							$categoryObj = new Category();
							$categoryIncr = $categoryObj->max('sort_order') + 1;
							$allPostPutVars['sort_order'] = $categoryIncr;
						}
						if (empty($allPostPutVars['store_id'])) {
							$allPostPutVars['store_id'] = $storeDetails['store_id'];
						}
						if (!empty($allPostPutVars['name'])) {
							$saveCategory = new Category($allPostPutVars);
							try {
								$saveCategory->save();
								if ($allPostPutVars['parent_id'] > 0) {
									$subategoryId = $saveCategory->xe_id;
									$ppAssetCatRelGtInit = new PrintProfileModels\PrintProfileAssetsCategoryRel();
									$relValueCount = $ppAssetCatRelGtInit->where('category_id', $allPostPutVars['parent_id'])->count();
									if ($relValueCount > 0) {
										$relValue = $ppAssetCatRelGtInit->where('category_id', $allPostPutVars['parent_id'])->get()->toArray();
										foreach ($relValue as $relValue) {
											$saveRelation[] = [
												'print_profile_id' => $relValue['print_profile_id'],
												'asset_type_id' => $assetTypeArr['asset_type_id'],
												'category_id' => $subategoryId,
											];
										}
										$ppAssetCatRelSaveInit = new PrintProfileModels\PrintProfileAssetsCategoryRel();
										$ppAssetCatRelSaveInit->insert($saveRelation);
									}
								}
								$jsonResponse = [
									'status' => 1,
									'message' => message('Category', 'saved'),
								];
							} catch (\Exception $e) {
								$serverStatusCode = EXCEPTION_OCCURED;
								create_log(
									'category',
									'error',
									[
										'message' => $e->getMessage(),
										'extra' => [
											'module' => 'Saving a category',
										],
									]
								);
							}
						}
					}
				}
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}
	/**
	 * Update Category according to the slug
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function updateCategory($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Category', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$assetTypeArr = $this->assetsTypeId($args['slug']);
		$getStoreDetails = get_store_details($request);
		$storeId = $getStoreDetails['store_id'];
		$isS3Enabled = $this->checkS3Settings($storeId);
		$cloudStorage = 0;
		if (!is_dir(CATEGORY_FOLDER)) {
			mkdir(CATEGORY_FOLDER, 0755);
		}
		$imageFileSize = $_FILES['image_file']['size'];
		//checking file size
		if ($imageFileSize > FILE_SIZE) {
			$jsonResponse = [
				'status' => 0,
				'message' => 'Sorry, your file is too large',
			];
		} else {
			if (
				!empty($args['slug'])
				&& !empty($assetTypeArr) && $assetTypeArr['status'] == 1
			) {
				$categoryId = isset($args['id']) ? $args['id'] : '';
				if (!empty($_FILES)) {
					$categoryUpdObj = new Category();
					$categoryData = $categoryUpdObj->where('xe_id', $categoryId)->select('*')->get()->toArray();
					$uploadedFile = do_upload('image_file', CATEGORY_FOLDER, [100], 'string');
					$originalFile = CATEGORY_FOLDER . $uploadedFile;
					$thumbFile = CATEGORY_FOLDER . 'thumb_' . $uploadedFile;
					//deleting original image file
					if (isset($thumbFile)) {
						unlink($originalFile);
					}
					foreach ($categoryData as $catValue) {
						if ($isS3Enabled) {
							if ($catValue['cloud_storage'] == 1) {
								$file = ASSETS_PATH_R . 'categories/' . 'thumb_' . $catValue['file_name'];
								$this->deleteS3File($file, $storeId);
							}
							$cloudStorage = 1;
							$fileToUpload = CATEGORY_FOLDER . 'thumb_' . $uploadedFile;
							$this->uploadFileToS3("categories", $fileToUpload, $storeId);
						} else {
							//deleting of old folder from categories directory
							$this->deleteOldFile(
								'categories',
								'file_name',
								[
									'xe_id' => $categoryId,
								],
								CATEGORY_FOLDER
							);
						}
					}

					$updateCategory = [
						'name' => $allPostPutVars['name'],
						'file_name' => $uploadedFile,
						'cloud_storage' => $cloudStorage
					];
				} else {
					$updateCategory = [
						'name' => $allPostPutVars['name'],
						'cloud_storage' => $cloudStorage
					];
				}
				try {
					$categoryUpdObj = new Category();
					$categoryUpdObj->where('xe_id', $categoryId)
						->update($updateCategory);
					$jsonResponse = [
						'status' => 1,
						'message' => message('Category', 'updated'),
					];
					$this->memcache('deleteMulti', '', '', $args['slug'] . "_cat");
					if (!empty($args['id'])) {
						$ppAssetCatRelGtInit = new PrintProfileModels\PrintProfileAssetsCategoryRel();
						$printProfileIds = $ppAssetCatRelGtInit->where('category_id', $args['id'])->pluck('print_profile_id');
						$this->createUpdateAssetJsonCache($getStoreDetails['store_id'], $printProfileIds, $args['slug'], $request, $response);
					}
				} catch (\Exception $e) {
					$serverStatusCode = EXCEPTION_OCCURED;
					create_log(
						'category',
						'error',
						[
							'message' => $e->getMessage(),
							'extra' => [
								'module' => 'Updating a category',
							],
						]
					);
				}
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Disable/Enable a category according to the current status of the category
	 * in the table
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function disableCategory($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Category', 'error'),
		];
		if (!empty($args) && $args['id'] > 0 && !empty($args['slug'])) {
			$categoryId = to_int($args['id']);
			$slug = trim($args['slug']);
			$assetTypeArr = $this->assetsTypeId($slug);
			if (
				!empty($slug)
				&& !empty($assetTypeArr)
				&& $assetTypeArr['status'] == 1
			) {
				$getCategoryInit = new Category();
				$category = $getCategoryInit->find($categoryId);
				if ($category->parent_id == 0) {
					$cateObj = new Category();
					$getSubCat = $cateObj->where(
						[
							'parent_id' => $category->xe_id,
							'asset_type_id' => $assetTypeArr['asset_type_id'],
						]
					)
						->get();
					foreach ($getSubCat as $subCatValue) {
						$subCatValue->is_disable = !$category->is_disable;
						$subCatValue->save();
					}
				}
				if ($category->is_default === 1) {
					$category->is_default = !$category->is_default;
				}
				$category->is_disable = !$category->is_disable;

				try {
					$category->save();
					$jsonResponse = [
						'status' => 1,
						'message' => message('Category', 'done'),
					];
					if (!empty($args['id'])) {
						$ppAssetCatRelGtInit = new PrintProfileModels\PrintProfileAssetsCategoryRel();
						$printProfileIds = $ppAssetCatRelGtInit->where('category_id', $args['id'])->pluck('print_profile_id');
						$this->createUpdateAssetJsonCache($storeId, $printProfileIds, $args['slug'], $request, $response);
					}
				} catch (\Exception $e) {
					$serverStatusCode = EXCEPTION_OCCURED;
					create_log(
						'category',
						'error',
						[
							'message' => $e->getMessage(),
							'extra' => [
								'module' => 'Disabling a category',
							],
						]
					);
				}
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Delete a category according to the current status of the category
	 * in the table
	 *
	 * @param $slug       asset slug
	 * @param $categoryId category Id
	 * @param $moduleDir  Module Directore
	 * @param $modelName  Module Name
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function deleteCat($storeId, $slug, $categoryId, $moduleDir, $modelName)
	{
		$modelPath = 'App\\Modules\\' . $moduleDir . '\\' . 'Models' . '\\';
		$modelPath .= $modelName;
		$categoryRelInit = new $modelPath();
		$assetTypeArr = $this->assetsTypeId($slug);
		if (!empty($slug) && !empty($assetTypeArr['status'])) {
			$deleteId = $categoryId;
			$categoryInit = new Category();
			$category = $categoryInit->where('xe_id', $deleteId)
				->orWhere('parent_id', $deleteId);
			if ($category->count() > 0) {
				try {
					//getting category image path and deleting it
					$getCategories = $categoryInit->select('file_name', 'cloud_storage')
						->where(
							['xe_id' => $deleteId]
						)
						->first()->toArray();
					$fileName = $getCategories['file_name'];
					$thumbFile = 'thumb' . '_' . $fileName;
					$filePath =  CATEGORY_FOLDER . $fileName;
					$thumbFilePath = CATEGORY_FOLDER . $thumbFile;
					if ($getCategories['cloud_storage'] == 1) {
						$thumb = ASSETS_PATH_R . 'categories/' . $thumbFile;
						$this->deleteS3File($thumb, $storeId);
					}
					unlink($filePath);
					unlink($thumbFilePath);
					$category->delete();
					$categoryRelInit->where(['category_id' => $deleteId])->delete();
					$jsonResponse = [
						'status' => 1,
						'message' => message('Category', 'deleted'),
					];
				} catch (\Exception $e) {
					create_log(
						'Category',
						'error',
						[
							'message' => $e->getMessage(),
							'extra' => [
								'module' => 'Delete a category',
							],
						]
					);
				}
			}
		}
		//clean the cache json stored for template listing in CMS page
		$folderPath = ASSETS_PATH_W . 'cache/design_assets/';
		// Check if the folder exists
		if (is_dir($folderPath)) {
			$dir = opendir($folderPath);
			if ($slug == 'templates') {
				$deleteFIle = 'template';
				//Flush Memcached

			} else {
				$deleteFIle = $slug;
			}
			$this->memcache('deleteMulti', '', '', $slug . "_cat");
			while (($file = readdir($dir)) !== false) {
				if (strpos($file, $deleteFIle) !== false) {
					$filePath = $folderPath . $file;
					if (is_file($filePath)) {
						unlink($filePath); // Delete the file
					}
				}
			}
			closedir($dir);
		}
		return $jsonResponse;
	}

	/**
	 * Sort categories according to the json response from frontend
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function sortCategory($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Category', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$sortData = $allPostPutVars['sort_data'];
		$sortDataArray = json_clean_decode($sortData, true);

		$assetTypeArr = $this->assetsTypeId($args['slug']);

		if (!empty($args['slug']) && !empty($assetTypeArr['status'])) {
			if (!empty($sortDataArray)) {
				foreach ($sortDataArray as $category) {
					$sortedData[] = [
						'parent' => 0,
						'child' => $category['id'],
					];
					if (!empty($category['children'])) {
						foreach ($category['children'] as $child) {
							$sortedData[] = [
								'parent' => $category['id'],
								'child' => $child['id'],
							];
						}
					}
				}
			}
			// Final procesing: Set a update array and Update the each record
			$updateSortedData = [];
			$updateStatus = 0;
			if (!empty($sortedData)) {
				foreach ($sortedData as $sortKey => $data) {
					$updateSortedData[] = [
						'parent_id' => $data['parent'],
						'sort_order' => $sortKey + 1,
					];
					$updCategoryObj = new Category();
					try {
						$updCategoryObj->where('xe_id', $data['child'])
							->update(['sort_order' => $sortKey + 1, 'parent_id' => $data['parent']]);
						$updateStatus++;
					} catch (\Exception $e) {
						create_log(
							'Category',
							'error',
							[
								'message' => $e->getMessage(),
								'extra' => [
									'module' => 'Sorting of categories',
								],
							]
						);
					}
				}
				//clean the cache json stored for template listing in CMS page
				$folderPath = ASSETS_PATH_W . 'cache/design_assets/';
				// Check if the folder exists
				if (is_dir($folderPath)) {
					$dir = opendir($folderPath);
					if ($args['slug'] == 'templates') {
						$deleteFIle = 'template';
					} else {
						$deleteFIle = $args['slug'];
					}
					while (($file = readdir($dir)) !== false) {
						if (strpos($file, $deleteFIle) !== false) {
							$filePath = $folderPath . $file;
							if (is_file($filePath)) {
								unlink($filePath); // Delete the file
							}
						}
					}
					closedir($dir);
				}

				// Setup Response
				if (!empty($updateStatus)) {
					$jsonResponse = [
						'status' => 1,
						'message' => message('Category', 'done'),
					];
				}
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Set a Category & Subcategory as Default
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return json
	 */
	public function setDefault($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Category', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$defaultIds = $allPostPutVars['default'];
		$assetTypeArr = $this->assetsTypeId($args['slug']);

		if (!empty($args['slug']) && !empty($assetTypeArr['status'])) {
			/**
			 * For easy processing and less coding :- If invalid/blank data come
			 * from frontend then convert to a blank JSON object or assign the
			 * valid JSON to a variable for durther processing
			 */
			if (!empty($defaultIds)) {
				$processingIds = $defaultIds;
			} else {
				$processingIds = '[]';
			}

			$getDefaultIds = json_clean_decode($processingIds, true);
			$getCategoryInit = new Category();
			$categories = $getCategoryInit->whereIn('xe_id', $getDefaultIds);
			if ($categories->count() > 0) {
				try {
					// Set default by asset type id
					$getCategoryInit = new Category();
					$getCategoryInit->where(
						[
							'is_default' => 1,
							'asset_type_id' => $assetTypeArr['asset_type_id'],
						]
					)->update(['is_default' => 0]);

					$getCategoryInit = new Category();
					$getCategoryInit->whereIn(
						'xe_id',
						$getDefaultIds
					)->update(['is_default' => 1]);

					$jsonResponse = [
						'status' => 1,
						'message' => message('Category', 'done'),
					];
				} catch (\Exception $e) {
					$serverStatusCode = EXCEPTION_OCCURED;
					create_log(
						'category',
						'error',
						[
							'message' => $e->getMessage(),
							'extra' => [
								'module' => 'Setting a category as Default',
							],
						]
					);
				}
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Save Tags of all modules
	 *
	 * @param $storeId Store ID
	 * @param $tags    (in comma separated)
	 *
	 * @author tanmayap@riaxe.com
	 * @date   06 Feb 2020
	 * @return boolean
	 */
	public function saveTags($storeId, $tags)
	{
		// Save Clipart and tags relation
		$updatedTagIds = [];
		if (!empty($tags)) {
			$tagsArray = explode(',', $tags);
			foreach ($tagsArray as $tag) {
				$conditions = [
					'name' => trim($tag),
					'store_id' => $storeId,
				];
				$tagObj = new Tag();
				$tagCount = $tagObj->where($conditions);
				if ($tagCount->count() == 0) {
					$tagObj = new Tag($conditions);
					$tagObj->save();
					$tagID = $tagObj->xe_id;
				} else {
					$getTagDetails = $tagCount->select('xe_id')
						->first();
					$tagID = $getTagDetails['xe_id'];
				}
				if (!empty($tagID)) {
					$updatedTagIds[] = to_int($tagID);
				}
			}
		}

		return $updatedTagIds;
	}

	/**
	 * Save design data to database and json data to a file
	 *
	 * @param $data    Design data database array
	 * @param $json    JSON data
	 * @param $options Other extra options/params
	 *
	 * @author tanmayap@riaxe.com
	 * @date   21 Feb 2020
	 * @return integer
	 */
	public function saveDesignData($data, $json, $options)
	{
		$customDesignId = 0;
		if (!empty($data) && !empty($options['directory'])) {
			$svgSaveLoc = path('abs', 'design_state') . $options['directory'];
			if (isset($options['save_type']) && $options['save_type'] == 'update' && !empty($options['design_id'])) {
				$customDesignId = $options['design_id'];
				$saveDesignStateInit = new \App\Components\Models\DesignStates();
				$saveDesignStateInit->where('xe_id', $customDesignId)
					->update($data);
			} else {
				$saveDesignStateInit = new \App\Components\Models\DesignStates(
					$data
				);
				$saveDesignStateInit->save();
				$customDesignId = $saveDesignStateInit->xe_id;
			}
			if ($customDesignId > 0 && !empty($json)) {
				// Save json data into json file
				$dirAccToRefId = "REF_ID_" . $customDesignId;
				$captureCSVLocation = path('abs', 'template') . $dirAccToRefId;
				create_directory($captureCSVLocation);
				create_directory($svgSaveLoc);
				$saveLocation = $svgSaveLoc . '/' . $customDesignId . '.json';
				write_file($saveLocation, $json);
				$this->generateDesignFiles($json, $customDesignId);
			}
		}

		return $customDesignId;
	}

	/**
	 * Save design svg files
	 *
	 * @param $designFiles    Design files array
	 * @param $customDesignId Custom Design Id
	 *
	 * @author tanmayap@riaxe.com
	 * @author debashrib@riaxe.com
	 * @date   07 Jan 2020
	 * @return boolean
	 */
	public function saveDesignFile($designFiles, $customDesignId)
	{
		if (!empty($designFiles)) {
			$dirAccToDesignId = "REF_ID_" . $customDesignId;
			$captureCSVLocation = path('abs', 'template') . $dirAccToDesignId;

			create_directory($captureCSVLocation);
			// Loop through the sides and save each SVG file
			foreach ($designFiles as $svgFileKey => $svgFile) {
				$svgFileSideIndex = "side_" . ($svgFileKey + 1) . '_';
				$svgCodeContent = urldecode($svgFile['svg']);
				$svgSaveLocation = $captureCSVLocation . '/'
					. $svgFileSideIndex . $dirAccToDesignId . '.svg';
				write_file($svgSaveLocation, $svgCodeContent);
			}
		}
	}

	/**
	 * Get data for Dashboard
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   07 Feb 2020
	 * @return json
	 */
	public function getDashboardData($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Dashboard', 'error'),
		];
		$dashboardData = $otherData = [];
		$storeDetails = get_store_details($request);
		// Get total product count
		$productCountArr = call_curl(
			[],
			'products/count',
			'GET'
		);
		// Get print profile data
		$printProfileCountArr = call_curl(
			[],
			'print-profiles/count',
			'GET'
		);
		$printProfileInit = new PrintProfileModels\PrintProfile();
		$getNonPriceSettingsCount = $printProfileInit->where('is_price_setting', 0)->count();
		$noAssetRelCount = DB::table("print_profiles")->select('xe_id')->whereNotIn(
			'xe_id',
			function ($query) {
				$query->select('print_profile_id')->from('print_profile_assets_category_rel')->distinct();
			}
		)->count('xe_id');
		// Get product count whose setting is incomplete
		$totalDecoProduct = DB::table('product_settings')
			->select('product_id')->distinct()
			->where('store_id', $storeDetails['store_id'])
			->count();
		$incompProduct = $productCountArr['total'] - $totalDecoProduct;

		// Get product count whose print profile is not set
		$printProfileSetting = DB::table('product_settings')->select('product_id')
			->where('store_id', $storeDetails['store_id'])
			->whereIn(
				'xe_id',
				function ($query) {
					$query->select('product_setting_id')->distinct()
						->from('print_profile_product_setting_rel');
				}
			)
			->count();
		$missingPrintProfile = $productCountArr['total'] - $printProfileSetting;

		// Get template data
		$templatesCount = DB::table('templates')->where(
			'store_id',
			$storeDetails['store_id']
		)
			->count();

		if (!empty($productCountArr)) {
			$otherData = [
				"total_product" => (isset($productCountArr['total'])
					&& $productCountArr['total'] > 0)
					? $productCountArr['total'] : 0,
				"templates" => ($templatesCount > 0) ? $templatesCount : 0,
				"incomplete_product" => ($incompProduct > 0)
					? $incompProduct : 0,
				"missing_print_profile" => ($missingPrintProfile > 0)
					? $missingPrintProfile : 0,
				"missing_print_profile_pricing" => ($getNonPriceSettingsCount > 0)
					? $getNonPriceSettingsCount : 0,
				"no_assets_relation_print_profiles" => ($noAssetRelCount > 0)
					? $noAssetRelCount : 0,
				"max_upload_file_size" => !empty($this->getUploadFileSize())
					? $this->getUploadFileSize() : "",
				"max_asset_upload_limit" => MAX_ASSET_UPLOAD_LIMIT
			];
			$dashboardData = array_merge($otherData, $printProfileCountArr);
			$jsonResponse = [
				'status' => 1,
				'data' => $dashboardData,
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Getting maximum upload file size from php ini settings
	 *
	 * @author divya@imprintnext.com
	 * @date   07 Feb 2024
	 * @return a string (size value)
	 */
	public function getUploadFileSize()
	{
		$maxFileSizeFromIni = ini_get('upload_max_filesize');
		$actualNumericVal = intval(preg_replace('/[^0-9]/', '', $maxFileSizeFromIni));
		if (strpos($maxFileSizeFromIni, 'G') !== false) {
			$actualNumericVal = $actualNumericVal * 1000;
		}
		$percentage = 25;
		$actualFileSize = $actualNumericVal - ($percentage / 100) * $actualNumericVal;
		return $actualFileSize . "MB";
	}

	/**
	 * GET: Get active store's details from database
	 *
	 * @author tanmayap@riaxe.com
	 * @date   5 Oct 2019
	 * @return Array
	 */
	public function getActiveStoreDetails()
	{
		$storeDetails = [];
		$databaseStoreInfo = DB::table('stores')
			->where('status', 1);
		if ($databaseStoreInfo->count() > 0) {
			$storeData = $databaseStoreInfo->first();
			if (!empty($storeData->xe_id) && $storeData->xe_id > 0) {
				$storeDetails = [
					'store_id' => $storeData->xe_id,
				];
			}
		}
		return $storeDetails;
	}
	// /**
	//  * GET: Get Attribute Pricing Details
	//  *
	//  * @param $productDetails Product Details
	//  * @param $productId      Product Id
	//  *
	//  * @author satyabratap@riaxe.com
	//  * @date   13 Feb 2020
	//  * @return Array of pricing
	//  */
	// public function getPriceDetails($productDetails, $productId)
	// {
	//     $productAttributes = [];
	//     if (!empty($productDetails) && !empty($productId)) {
	//         $attributeName = $this->getAttributeName();
	//         foreach ($productDetails as $attrKey => $attributes) {
	//             $attrDetails = $attrTerms = [];
	//             foreach ($attributes['options'] as $termKey => $termValue) {
	//                 $priceInit = new \App\Modules\Products\Models\AttributePriceRule();
	//                 $getPriceData = $priceInit->where(['product_id' => $productId, 'attribute_id' => $attributes['id'], 'attribute_term_id' => $termValue['id']])
	//                     ->select('print_profile_id', 'price');
	//                 $priceData = [];
	//                 if (isset($getPriceData) && $getPriceData->count() > 0) {
	//                     foreach ($getPriceData->get() as $priceKey => $priceValue) {
	//                         $priceData[$priceKey] = [
	//                             'print_profile_id' => $priceValue->print_profile_id,
	//                             'price' => $priceValue->price,
	//                         ];
	//                     }
	//                 }
	//                 $attrDetails = [
	//                     'id' => $termValue['id'],
	//                     'name' => $termValue['name'],
	//                 ];
	//                 if (!empty($attributeName) && $attributeName['color'] != "") {
	//                     if (isset($attributes['name'])
	//                         && $attributes['name'] === $attributeName['color']
	//                     ) {
	//                         $colorSwatchInit = new \App\Modules\Settings\Models\ColorSwatch();
	//                         $getTermLocalData = $colorSwatchInit->where('attribute_id', $termValue['id'])
	//                             ->first();
	//                         $attrDetails['hex_code'] = $attrDetails['file_name'] = "";
	//                         if (!empty($getTermLocalData['hex_code'])
	//                             && $getTermLocalData['hex_code'] != ""
	//                         ) {
	//                             $attrDetails['hex_code'] = $getTermLocalData['hex_code'];
	//                         }
	//                         if (!empty($getTermLocalData['file_name'])
	//                             && $getTermLocalData['file_name'] != ""
	//                         ) {
	//                             $attrDetails['file_name'] = $getTermLocalData['file_name'];
	//                         }
	//                     }
	//                 }
	//                 $attrDetails['price_data'] = $priceData;
	//                 $attrTerms[$termKey] = $attrDetails;
	//             }
	//             $productAttributes[$attrKey] = [
	//                 'id' => $attributes['id'],
	//                 'name' => $attributes['name'],
	//                 'attribute_term' => $attrTerms,
	//             ];
	//         }
	//     }

	//     return $productAttributes;
	// }

	/**
	 * Get: Get all errors and activity Logs stored in logs/ directory
	 * Helpful for developers to see errors/exceptions while developing
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author tanmayap@riaxe.com
	 * @date   20 Feb 2020
	 * @return html
	 */
	public function xeLogs($request, $response)
	{
		$logsData = [];
		$getFileLogs = [];
		$getFileLogs = read_logs('file');
		$getFileLogs = array_merge($getFileLogs, read_logs('activity'));

		foreach ($getFileLogs as $fLogKey => $fLog) {
			$eachLogToArray = json_clean_decode($fLog);
			$logsData[$fLogKey] = $eachLogToArray;
		}

		$htmlOutput = "<table border='1' width='100%'><tbody>";
		$htmlOutput .= "<tr><td>#</td><td>Message</td><td>Details</td><td>Level</td><td>DateTime</td></tr>";
		foreach ($logsData as $logsKey => $logs) {
			$htmlOutput .= "<tr>
                <td>" . ($logsKey + 1) . "</td>
                <td>" . $logs['message'] . "</td>
                <td>" . json_clean_encode($logs['context']) . "</td>
                <td>" . $logs['level_name'] . "</td>
                <td>" . date('d/M/Y h:i:s A', strtotime($logs['datetime']['date'])) . "</td>
            </tr>";
		}
		$htmlOutput .= "</tbody></table>";

		echo $htmlOutput;
	}

	/**
	 * Get: Get custom Preview Images
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   03 Mar 2020
	 * @return json
	 */
	public function getCustomPreviewImages($request, $response, $params = array())
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Preview images', 'error'),
		];
		if (empty($params)) {
			$token = $request->getQueryParam('token') ?
				$request->getQueryParam('token') : "";
			$decryptData = decryption($token);
			if (!empty($decryptData)) {
				$refIdProIdArray = explode("@", $decryptData);
				if (!empty($refIdProIdArray) && $refIdProIdArray[0] != "") {
					$customDesignId = $refIdProIdArray[0];
					if (array_key_exists(1, $refIdProIdArray)) {
						$productId = $refIdProIdArray[1];
					}
				}
			}
		} else {
			$customDesignId = $params['custom_design_id'];
			$productId = $params['product_id'];
		}
		$parentProductId = 0;
		if (strtolower(STORE_NAME) == "shopify") {
			$storeProductInit = new StoreProductsController();
			$parentProductID = $storeProductInit->getOriginalVarID($productId);
			$productId = $parentProductID;
		}
		if (strtolower(STORE_NAME) == "opencart") {
			$storeProductInit = new StoreProductsController();
			$parentProductId = $storeProductInit->getParentProductID($productId);
		}
		if (!empty($customDesignId) && !empty($productId)) {
			$stateDesignPath = path('abs', 'design_state') . 'carts/' . $customDesignId . '.json';
			if (!file_exists($stateDesignPath)) {
				$stateDesignPath = path('abs', 'design_state') . 'predecorators/' . $customDesignId . '.json';
				if (!file_exists($stateDesignPath)) {
					$stateDesignPath = path('abs', 'design_state') . 'artworks/' . $customDesignId . '.json';
				}
			}
			if (file_exists($stateDesignPath)) {
				$jsonData = json_clean_decode(file_get_contents($stateDesignPath), true);
				$nameAndNumber = 0;
				$customImageUrl = [];
				$attributeName = $this->getAttributeName();
				$colorAttr = $attributeName['color'];
				$sizeAttr = $attributeName['size'];
				$sizeLoop = sizeof($jsonData['sides']);
				if (!empty($jsonData)) {
					// get customImageUrl
					foreach ($jsonData['design_product_data'] as $designProductData) {
						if (is_array($designProductData) && in_array($productId, $designProductData['variant_id'])) {

							$customImageUrl = $designProductData['design_urls'];
							$variableDecorationSize = isset($designProductData['variable_decoration_size']) ? $designProductData['variable_decoration_size'] : '';
							$variableDecorationUnit = isset($designProductData['variable_decoration_unit']) ? $designProductData['variable_decoration_unit'] : '';
						}
					}
					if (empty($customImageUrl)) {
						$customImageUrl = $jsonData['design_product_data'][0]['design_urls'];
					}
					for ($i = 0; $i < $sizeLoop; $i++) {
						$designStatus = 0;
						$nameAndNumber = 0;
						$printId = $jsonData['sides'][0]['print_area'][0]['print_method_id'];
						$productUrl = '';
						$svgData = $jsonData['sides'][$i]['svg'];
						if ($svgData != '') {
							$designStatus = 1;
						}
						if (!empty($jsonData['name_number'])) {
							$nameAndNumber = 1;
						}
						if (!empty($jsonData['configurator_svg_info'])) {
							$cartEditSettings = 0;
						} else {
							$getStoreDetails = get_store_details($request);
							$settngs = $this->readSettingJsonFile($getStoreDetails['store_id']);
							$cartSetting = $settngs['cart'];
							if (!empty($cartSetting['cart_edit'])) {
								$cartEditSettings = ($cartSetting['cart_edit']['is_enabled']) ? $cartSetting['cart_edit']['is_enabled'] : 0;
							}
						}
						$images[] = [
							"design_status" => $designStatus,
							"customImageUrl" => $customImageUrl,
							"productImageUrl" => $productUrl,
							"printid" => $printId,
							"nameAndNumber" => $nameAndNumber,
							"display_edit" => $cartEditSettings,
							"colorAttr" => $colorAttr,
							"sizeAttr" => $sizeAttr,
							"simpleProductId" => $productId,
							"parentProductId" => $parentProductId,
							"variableDecorationSize" => $variableDecorationSize,
							"variableDecorationUnit" => $variableDecorationUnit,
							"refId" => $customDesignId,
						];
					}
					// $jsonResponse = $images;
					$jsonResponse = [
						$customDesignId => $images,
					];
				}
			}
		}
		if (empty($params)) {
			return response(
				$response,
				['data' => $jsonResponse, 'status' => $serverStatusCode]
			);
		} else {
			return $jsonResponse;
		}
	}

	/**
	 * Get: Get Setting Status
	 *
	 * @param $settingKey Setting key
	 * @param $type       Type
	 * @param $valueKey   Value Key
	 *
	 * @author debashrib@riaxe.com
	 * @date   19 Mar 2020
	 * @return json
	 */
	public function getSettingStatus($settingKey, $type, $valueKey)
	{
		$settingValue = 0;
		if (!empty($settingKey) && !empty($type)) {
			$settingStatus = DB::table('settings')
				->where(['setting_key' => $settingKey, 'type' => $type])
				->first();
			$settingData = $settingStatus->setting_value;
			$settingArray = json_clean_decode($settingData, true);
			$settingValue = (!empty($settingArray[$valueKey[0]])) ? $settingArray[$valueKey[0]] : 0;
			if (count($valueKey) > 1) {
				$settingValue = (!empty($settingArray[$valueKey[1]][$valueKey[0]]))
					? $settingArray[$valueKey[1]][$valueKey[0]] : 0;
			}
		}

		return $settingValue;
	}
	/**
	 * Save Captured Images
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Arguments
	 *
	 * @author tanmayap@riaxe.com
	 * @date   09 Feb 2020
	 * @return json
	 */
	public function saveCaptureImage($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$allPostPutVars = $request->getParsedBody();
		$getStoreDetails = get_store_details($request);
		$postType = !empty($args['save_type']) ? $args['save_type'] : '';
		$designId = !empty($args['design_id']) ? $args['design_id'] : '';
		$storeId = $allPostPutVars['store_id'] ? $allPostPutVars['store_id'] : 1;
		$source = $allPostPutVars['source'] ? $allPostPutVars['source'] : '';
		$generateThumb = [];
		$responseType = empty($args['return_type']) ? 'json' : 'array';
		$resourceAvailable = array('carts', 'templates', 'user_designs', 'quotes', 'shares');
		$isS3Enabled = $this->checkS3Settings($getStoreDetails['store_id']);
		// Thumb generation status
		if (!empty($allPostPutVars['thumb'])) {
			$generateThumb[] = $allPostPutVars['thumb'];
		}
		$getCapturedImages = [];
		$jsonResponse = [
			'status' => 0,
			'message' => message('Capture Image', 'error'),
		];
		// Get conditional resourse type
		$resourceType = '';
		if (!empty($allPostPutVars['type'])) {
			$resourceType = $allPostPutVars['type'];
		} elseif (!empty($args['type'])) {
			$resourceType = $args['type'];
		} else {
			$resourceType = '';
		}
		if (
			!empty($resourceType)
			&& in_array($resourceType, $resourceAvailable)
		) {
			$resourceDirW = path('abs', 'design_preview') . trim($resourceType);
			$resourceDirR = path('read', 'design_preview') . trim($resourceType);
			// Delete old files in case of update
			if (!empty($postType) && $postType == 'update' && !empty($designId)) {
				$svgJsonPath = path('abs', 'design_state') . 'user_designs';
				$absDesignPath = path('abs', 'design_preview') . 'user_designs';
				$svgJsonPath .= '/' . $designId . '.json';
				if (file_exists($svgJsonPath)) {
					$svgData = read_file($svgJsonPath);
					$svgDecodedData = json_clean_decode($svgData, true);
					if (!empty($svgDecodedData['capture_images'])) {
						foreach ($svgDecodedData['capture_images'] as $cKey => $capture) {
							if ($isS3Enabled) {
								$this->deleteS3File($capture['url'], $getStoreDetails['store_id']);
								$this->deleteS3File($capture['thumbnail'], $getStoreDetails['store_id']);
							} else {
								delete_file($absDesignPath . '/' . $capture['file_name']);
								delete_file($absDesignPath . '/thumb_' . $capture['file_name']);
							}
						}
					}
					delete_file($svgJsonPath);
				}
			}
			$getImageNames = do_upload(
				'images',
				$resourceDirW,
				$generateThumb,
				'array'
			);

			if (!empty($getImageNames)) {
				foreach ($getImageNames as $fileKey => $fileName) {
					if ($isS3Enabled) {
						$fileToUpload = $resourceDirW . '/' .  $fileName;
						$s3Url = $this->uploadFileToS3("design_preview", $fileToUpload, $getStoreDetails['store_id']);
						$getCapturedImages['images'][$fileKey] = [
							'url' => $s3Url['S3URL'],
						];
					} else {
						$getCapturedImages['images'][$fileKey] = [
							'url' => $resourceDirR . '/' . $fileName,
						];
					}
					// Send file_name according to the format requested
					if ($responseType == 'array') {
						$getCapturedImages['images'][$fileKey] += [
							'file_name' => $fileName,
						];
					}
					// Conditional thumnail response will go
					if (!empty($allPostPutVars['thumb'])) {
						if ($isS3Enabled) {
							$thumb = $resourceDirW . '/' . 'thumb_' . $fileName;
							$thumbUrl = $this->uploadFileToS3("design_preview", $thumb, $getStoreDetails['store_id']);
							$getCapturedImages['images'][$fileKey] += [
								'thumbnail' => $thumbUrl['S3URL'],
							];
						} else {
							$getCapturedImages['images'][$fileKey] += [
								'thumbnail' => $resourceDirR . '/' . 'thumb_' . $fileName,
							];
						}
					}
				}
				// Add the image url for sharing purpose.
				if ($resourceType == 'shares' && $getCapturedImages['images'][0]['url'] != "") {
					$this->updateImageUrl($getCapturedImages['images'][0]['url']);
				}
				if ($storeId > 1 && empty($source)) {
					$storeResponse = $this->getStoreDomainName($storeId);
					foreach ($getCapturedImages['images'] as $key => $value) {
						$hostname = parse_url($value['url'], PHP_URL_HOST);
						$getCapturedImages['images'][$key]['url'] = str_replace($hostname, $storeResponse['store_url'], $value['url']);
					}
				}
				$jsonResponse = [
					'status' => 1,
					'data' => $getCapturedImages,
				];
			}
		}

		if ($responseType == 'json') {
			return response(
				$response,
				['data' => $jsonResponse, 'status' => $serverStatusCode]
			);
		}
		return $getCapturedImages;
	}
	/**
	 * Update Image Url in the index file for sharing
	 *
	 * @param $imageUrl Image Url
	 *
	 * @author satyabratap@riaxe.com
	 * @date   17 Aug 2020
	 * @return json
	 */
	protected function updateImageUrl($imageUrl)
	{
		// Adding RVN Number in index.html page for fixing cache issue
		$indexFile = rtrim(RELATIVE_PATH, WORKING_DIR) . '/index.html';
		if (file_exists($indexFile)) {
			$getIndexContents = htmlspecialchars(file_get_contents($indexFile));
			$stringAfterFile = substr($getIndexContents, strpos($getIndexContents, "https://"));
			$oldImageUrl = substr($stringAfterFile, 0, strpos($stringAfterFile, '.png'));
			$getIndexContents = str_replace($oldImageUrl . '.png', $imageUrl, $getIndexContents);
			file_put_contents($indexFile, htmlspecialchars_decode($getIndexContents));
		}
	}
	/**
	 * Save the custom pattern file to the server
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Arguments
	 *
	 * @author tanmayap@riaxe.com
	 * @date   04 Apr 2020
	 * @return json
	 */
	public function savePattern($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'data' => [],
			'message' => message('Pattern', 'error'),
		];
		$directoryWrite = path('abs', 'design_preview') . 'augmented' . '/';

		$uploadedPattern = do_upload('upload', $directoryWrite, [], 'string');
		if (!empty($uploadedPattern)) {
			$sourceFile = $directoryWrite . $uploadedPattern;
			$destFile = $directoryWrite . 'custom_ar_pattern.patt';
			if (rename($sourceFile, $destFile)) {
				$jsonResponse = [
					'status' => 1,
					'message' => message('Pattern', 'saved'),
				];
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}
	/**
	 * Save the Augmented Reality Files and generate HTML file
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Arguments
	 *
	 * @author tanmayap@riaxe.com
	 * @date   29 mar 2020
	 * @return json
	 */
	public function saveAugmentData($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'data' => [],
			'message' => message('Augmented data', 'error'),
		];
		$augmentedData = [];
		$allowedFormats = [
			'jpeg' => 'image',
			'jpg' => 'image',
			'png' => 'image',
			'gif' => 'image',
			'swf' => 'media',
			'wav' => 'media',
			'mp4' => 'media',
			'mpg' => 'media',
			'wmv' => 'media',
			'avi' => 'media',
			'gltf' => 'object',
		];

		$resourceDirW = path('abs', 'design_preview');
		$resourceDirR = path('read', 'design_preview');
		$saveAugPath = $resourceDirW . 'augmented' . '/';
		$fetchAugPath = $resourceDirR . 'augmented' . '/';
		$htmlName = getRandom() . '.html';
		$saveHtmlFilePath = $resourceDirW . 'augmented' . '/' . $htmlName;
		$getHtmlFilePath = $resourceDirR . 'augmented' . '/' . $htmlName;

		$commonFolder = path('abs', 'common');
		$masterHtmlFile = file_get_contents($commonFolder . '/augmented-reality-master.html');

		$uploadedFiles = do_upload('upload', $saveAugPath, [150], 'array');
		if (!empty($uploadedFiles)) {
			$generateCore = "";
			foreach ($uploadedFiles as $key => $upload) {
				$selectedType = null;
				$uploadedFile = $upload;
				$sourceFile = $fetchAugPath . $upload;
				$augmentedData['files'][] = $fetchAugPath . $upload;
				$extension = pathinfo($sourceFile, PATHINFO_EXTENSION);
				$extension = strtolower($extension);

				if (in_array($extension, array_keys($allowedFormats)) && !empty($allowedFormats[$extension])) {
					$selectedType = $allowedFormats[$extension];
					$sourceByExt = ${$selectedType . 'Html'};
					$generateCore .= str_replace("[SOURCE]", $sourceFile, $sourceByExt);
				}
			}

			$finalHtmlCodes = str_replace("[DYNAMIC_SOURCE]", $generateCore, $masterHtmlFile);

			// Selecting right pattern file
			$selectedPattern = '';
			$defaultPattFile = path('abs', 'common') . 'default_ar_pattern.patt';
			$customPattFile = $saveAugPath . 'custom_ar_pattern.patt';
			if (file_exists($customPattFile)) {
				$selectedPattern = $fetchAugPath . 'custom_ar_pattern.patt';
			} elseif (file_exists($defaultPattFile)) {
				$selectedPattern = path('read', 'common') . 'default_ar_pattern.patt';
			} else {
				$selectedPattern = '';
			}
			if (!empty(selectedPattern)) {
				$finalHtmlCodes = str_replace("[PATTERN_URL]", $selectedPattern, $finalHtmlCodes);
			}

			if (write_file($saveHtmlFilePath, $finalHtmlCodes)) {
				// Save in database
				$data = [
					// did not decided wheather to save single file ot multiple file
					'file' => $uploadedFile,
					'html_file' => $htmlName,
				];
				$augmented = new \App\Components\Models\AugmentedReality($data);
				if ($augmented->save()) {
					$augmentedId = $augmented->xe_id;
					$augmentedData['last_insert_id'] = $augmentedId;
					$augmentedData['html'] = $getHtmlFilePath;
					$jsonResponse = [
						'status' => 1,
						'data' => $augmentedData,
						'message' => message('Augmented Data', 'saved'),
					];
				}
			}
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Update Revision Number For Clearing Cache
	 *
	 * @param $storeId Store Id
	 *
	 * @author satyabratap@riaxe.com
	 * @date   5 May 2020
	 * @return Boolean
	 */
	public function updateRevisionNo($storeId)
	{
		$settingInit = new \App\Modules\Settings\Models\Setting();
		$revNo = $settingInit->where('setting_key', '=', 'revision_no')->first();
		$newRevNo = $revNo->setting_value + 1;
		$settingInit->where('setting_key', '=', 'revision_no')
			->update(['setting_value' => $newRevNo]);
		$staticFolderPath = rtrim(RELATIVE_PATH, WORKING_DIR);
		$configPath = $staticFolderPath . '/' . 'config.js';
		$fileContents = file_get_contents($configPath);
		if (strpos($fileContents, "RVN") !== false) {
			$revNo = strtok(substr($fileContents, strpos($fileContents, "RVN")), ',');
			$newContents = str_replace($revNo, "RVN = " . (int) ($newRevNo), $fileContents);
			file_put_contents($configPath, $newContents);
			return (int) ($newRevNo);
		}
		return false;
	}

	/**
	 * Create name and number CSV file
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Arguments
	 *
	 * @author radhanatham@riaxe.com
	 * @date   05 June 2020
	 * @return json
	 */
	public function createNameNumberCsvSample($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'data' => [],
			'message' => message('Name And Number Sample', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$teamMembers = $allPostPutVars['teamMembers'] ? $allPostPutVars['teamMembers'] : '';

		$nameNumberArray = json_clean_decode($teamMembers, true);
		$nameNumberAssetsPath = path('abs', 'name_number');
		if (!is_dir($nameNumberAssetsPath)) {
			mkdir($nameNumberAssetsPath, 0755);
		}
		if (!empty($nameNumberArray)) {
			$headerData = $nameNumberArray[0];
			$rowData = $nameNumberArray;
			if ($fileName == '') {
				$randNo = getRandom();
				$csvFilename = $randNo . '.csv';
				$zipName = $randNo . '.zip';
				$isZip = $this->jsonToCSV($rowData, $csvFilename, $headerData, $nameNumberAssetsPath, $randNo);
				if ($isZip) {
					$returnFileName = $zipName;
				} else {
					$returnFileName = $csvFilename;
				}
				$jsonResponse = [
					'status' => 1,
					'data' => $returnFileName,
					'message' => message('Name And Number Sample', 'saved'),
				];
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * GET: Convert JSON file to CSV file and save corresponding directory
	 *
	 * @param $data                 Array data
	 * @param $cfilename            CSV file name
	 * @param $headerData           CSV header row data
	 * @param $nameNumberAssetsPath This is for directory for save CSV file
	 *
	 * @author radhanatham@riaxe.com
	 * @date   05 June 2020
	 * @return boolean
	 */
	private function jsonToCSV($data, $cfilename, $headerData, $nameNumberAssetsPath, $randNo)
	{
		$templateImagePath = path('abs', 'product');
		$deisgnPreviewPath = path('abs', 'design_preview') . 'carts';
		$templatesDesignPrvPath = path('abs', 'design_preview') . 'templates';
		$header = [];
		if (!empty($headerData)) {
			foreach ($headerData as $k => $v) {
				if ($v['type'] != 'remove') {
					$header[] = $v['name'];
				}
			}
			$rows = [];
			$rows[0] = $header;
			$isZip = false;
			$imagePath = $nameNumberAssetsPath . '/' . $randNo;
			foreach ($data as $key => $value) {
				foreach ($value as $k => $row) {
					if ($row['type'] != 'remove') {
						if ($row['type'] == 'image') {
							$isZip = true;
							if (!is_dir($imagePath)) {
								create_directory($imagePath);
							}
							$fileName = basename($row['value']);
							if (
								strpos($row['value'], "products") !== false
							) {
								$pngFilePath = $templateImagePath . $fileName;
							} elseif (strpos($row['value'], "templates") !== false) {
								$pngFilePath = $templatesDesignPrvPath . '/' . $fileName;
							} else {
								$pngFilePath = $deisgnPreviewPath . '/' . $fileName;
							}
							$customizeImage = read_file($pngFilePath);
							if (is_dir($imagePath)) {
								$nameNumberPathFile = $imagePath . '/' . $fileName;
								if (!file_exists($nameNumberPathFile)) {
									write_file($nameNumberPathFile, $customizeImage);
								}
							}
							$rows[$key + 1][] = basename($row['value']);
						} else {
							if ($row['type'] == 'name') {
								$rows[$key + 1][] = $row['placeholder'];
							} elseif ($row['type'] == 'number') {
								$rows[$key + 1][] = $row['placeholder'];
							} else {
								$rows[$key + 1][] = $row['value'];
							}
						}
					}
				}
			}
			if (!empty($rows)) {
				$cfilename = $nameNumberAssetsPath . '/' . $cfilename;
				if (file_exists($nameNumberAssetsPath)) {
					$fp = fopen($cfilename, 'w');
					foreach ($rows as $fields) {
						fputcsv($fp, $fields);
					}
				}
				fclose($fp);

				if ($isZip) {
					$this->createNameNumberZip($imagePath, $randNo, $nameNumberAssetsPath, $cfilename);
				}
			}
		}
		return $isZip;
	}

	/**
	 * Create name and number sample download zip file
	 *
	 * @param $imagePath            Image Path
	 * @param $randNo               Random number
	 * @param $nameNumberAssetsPath Asset path
	 * @param $cfilename            CSV file path
	 *
	 * @author radhanatham@riaxe.com
	 * @date   05 June 2020
	 * @return nothing
	 */
	private function createNameNumberZip($imagePath, $randNo, $nameNumberAssetsPath, $cfilename)
	{
		$assetFileExt = 'svg,pdf,png,jpeg,jpg,gif,bmp,ai,psd,eps,cdr,dxf,tif';
		$zipName = $randNo . '.zip';
		$zip = new Zipper();
		$zip->make($nameNumberAssetsPath . '/' . $zipName);
		if (is_dir($imagePath)) {
			$zip->add($cfilename, $randNo . '.csv');
			$zip->addEmptyDir(
				"/image"
			);
			$urlAsset = $imagePath;
			$addPath = "/image/";
			$optionsAsset = array(
				'add_path' => $addPath,
				'remove_path' => $urlAsset,
			);
			$zip->addGlob(
				$urlAsset . '/*{' . $assetFileExt . '}',
				$optionsAsset
			);
			$zip->close();
			delete_file($cfilename);
			delete_directory($imagePath);
			rmdir($imagePath);
		}
	}

	/**
	 * Download name and number csv sample file
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Arguments
	 *
	 * @author radhanatham@riaxe.com
	 * @date   05 June 2020
	 * @return json
	 */
	public function downloadNameNumberCsvSample($request, $response, $args)
	{
		$fileName = $request->getQueryParam('file_name') ? $request->getQueryParam('file_name') : '';
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'data' => [],
			'message' => message('Name And Number Sample', 'error'),
		];

		$nameNumberAssetsPath = path('abs', 'name_number');
		if ($fileName != '') {
			$downloadFilepath = $nameNumberAssetsPath . '/' . $fileName;
			if (file_exists($downloadFilepath)) {
				file_download($downloadFilepath);
				$status = 1;
				$message = 'Name And Number Sample File Downloaded Successful';
			} else {
				$status = 0;
				$message = 'Error In Name And Number Sample File Download';
			}
			$jsonResponse = [
				'status' => $status,
				'message' => $message,
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Save Production Status
	 *
	 * @param $statusData Data Array
	 *
	 * @author debashrib@riaxe.com
	 * @date   17 Apr 2019
	 * @return last insert id
	 */
	private function saveStatusData($statusData, $moduleId)
	{
		$statusLastId = 0;
		if (!empty($statusData)) {
			$productionSatus = new ProductionStatus($statusData);
			if (isset($moduleId) && $moduleId == 3) {
				$productionSatus = new PurchaseOrderStatus($statusData);
			}
			if ($productionSatus->save()) {
				$statusLastId = $productionSatus->xe_id;
			}
		}
		return $statusLastId;
	}

	/**
	 * GET: Production Status
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   24 mar 2019
	 * @return json response
	 */
	/**
	 * GET: Production Status
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   24 mar 2019
	 * @return json response
	 */
	public function getProductionStatus($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Status', 'error'),
		];
		$getStoreDetails = get_store_details($request);
		$moduleId = $request->getQueryParam('module_id');
		$productionStatusInit = new ProductionStatus();
		if (isset($moduleId) && $moduleId == 3) {
			$productionStatusInit = new PurchaseOrderStatus();
		}
		$getProductionStatus = $productionStatusInit
			->where('store_id', $getStoreDetails['store_id']);
		if (isset($moduleId) && $moduleId != '') {
			$getProductionStatus->where('module_id', $moduleId);
		}
		if ($getProductionStatus->count() > 0) {
			$getProductionStatusData = $getProductionStatus->get();
			$jsonResponse = [
				'status' => 1,
				'data' => $getProductionStatusData,
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * POST: Save Production Tags
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   24 mar 2019
	 * @return json response wheather data is saved or any error occured
	 */
	public function saveProductionTags($request, $response)
	{
		$getStoreDetails = get_store_details($request);
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Status', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$allPostPutVars['store_id'] = $getStoreDetails['store_id'];
		$tagLastId = $this->saveTagsData($allPostPutVars);
		if ($tagLastId > 0) {
			$jsonResponse = [
				'status' => 1,
				'tag_id' => $tagLastId,
				'message' => message('Status', 'saved'),
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Save Production tags
	 *
	 * @param $tagData Data Array
	 *
	 * @author debashrib@riaxe.com
	 * @date   17 Apr 2019
	 * @return last insert id
	 */
	private function saveTagsData($tagData)
	{
		// Save Production Tags Data
		$tagLastId = 0;
		if (!empty($tagData)) {
			$productionTags = new ProductionTags($tagData);
			if ($productionTags->save()) {
				$tagLastId = $productionTags->xe_id;
			}
		}
		return $tagLastId;
	}

	/**
	 * GET: Production Tags
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   24 mar 2019
	 * @return json response
	 */
	public function getProductionTags($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Tags', 'error'),
		];
		$getStoreDetails = get_store_details($request);
		$moduleId = $request->getQueryParam('module_id');
		$productionTagsInit = new ProductionTags();
		$getProductionTags = $productionTagsInit
			->where('store_id', $getStoreDetails['store_id']);
		if (isset($moduleId) && $moduleId != '') {
			$getProductionTags->where('module_id', $moduleId);
		}
		if ($getProductionTags->count() > 0) {
			$getProductionTagsData = $getProductionTags->get();
			$jsonResponse = [
				'status' => 1,
				'data' => $getProductionTagsData,
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * POST: Save Production Hub Setting
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   04 Apr 2019
	 * @return json response wheather data is saved or any error occured
	 */
	public function saveProductionSetting($request, $response)
	{
		$getStoreDetails = get_store_details($request);
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Production Hub Setting', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		if (
			isset($allPostPutVars['settings'])
			&& $allPostPutVars['settings'] != ""
		) {
			$settingsArray = json_clean_decode($allPostPutVars['settings'], true);
			/** new code for payment settings */
			$isPaymentEnable =  $settingsArray['data']['is_payment_enable'] ? $settingsArray['data']['is_payment_enable'] : 0;
			$isSelected = 1;
			$isDeletePaymnetData = true;
			$paymentType = '';
			if (!empty($settingsArray['payment_methods'])) {
				$selectedIndex = array_search($isSelected, array_column($settingsArray['payment_methods'], 'is_selected'));
				$activePaymentMethodData =  $settingsArray['payment_methods'][$selectedIndex]['payment_setting'];
				$paymentType = strtolower($settingsArray['payment_methods'][$selectedIndex]['payment_type']);
				$paymentTypeId =  $settingsArray['payment_methods'][$selectedIndex]['xe_id'];
			}

			$getPaymentSettingFromDb = [];
			if ($isPaymentEnable == true) {
				if ($paymentType == "stripe") {
					if (empty($activePaymentMethodData['publishable_key']) && empty($activePaymentMethodData['secret_key'])) {
						$paymentSettingInit = new QuotationPaymentSettings();
						$getPaymentSetting =  $paymentSettingInit->where(['payment_method_id' => $paymentTypeId]);
						if ($getPaymentSetting->count() > 0) {
							$paymentSettingData =  $getPaymentSetting->get()->toArray();
							foreach ($paymentSettingData as $key => $value) {
								$keyName = $value['keyname'];
								$keyValue = $this->decryptKey($value['keyvalue']);
								$getPaymentSettingFromDb[$keyName] = $keyValue;
							}
						}
					}
				} else {
					if (empty($activePaymentMethodData['merchant_email_id'])) {
						$paymentSettingInit = new QuotationPaymentSettings();
						$getPaymentSetting =  $paymentSettingInit->where(['payment_method_id' => $paymentTypeId]);
						if ($getPaymentSetting->count() > 0) {
							$paymentSettingData =  $getPaymentSetting->get()->toArray();
							foreach ($paymentSettingData as $key => $value) {
								$keyName = $value['keyname'];
								$keyValue = $this->decryptKey($value['keyvalue']);
								$getPaymentSettingFromDb[$keyName] = $keyValue;
							}
						}
					}
				}
				if (!empty($getPaymentSettingFromDb)) {
					$settingsArray['payment_methods'][$selectedIndex]['payment_setting'] = $getPaymentSettingFromDb;
				}
			}

			/** new code for payment settings */
			$moduleId = $settingsArray['module_id'];
			$settingInit = new ProductionHubSetting();

			if ($moduleId == 1) {
				//Get old quote_id from setting
				$oldQuoteData = $this->getOldQuoteId($getStoreDetails['store_id']);
				$oldQuoteId = $oldQuoteData['quote_id'];
				$oldCompanyLogo = json_clean_decode($oldQuoteData['company_logo'], true);
			}
			if ($moduleId == 4) {
				//Get old job_card from setting
				$oldJobCardData = $this->getOldJobId($getStoreDetails['store_id']);
				$oldJobId = $oldJobCardData['job_card'];
			}
			if ($moduleId == 3) {
				//Get old purchase_order_id from setting
				$oldPOData = $this->getOldPOId($getStoreDetails['store_id']);
				$oldPOId = $oldPOData['purchase_order_id'];
			}
			$settingInit->where(
				[
					'module_id' => $moduleId,
					'store_id' => $getStoreDetails['store_id'],
				]
			)->delete();
			$settingDataArr = $settingsArray['data'];
			$newQuoteId = $settingDataArr['quote_id'];
			$newJobId = $settingDataArr['job_card'];
			$newPOId = $settingDataArr['purchase_order_id'];
			//Quotation status
			$statusArr = (isset($settingsArray['status']) && !empty($settingsArray['status']))
				? $settingsArray['status'] : [];

			if (!empty($statusArr)) {
				$this->statusOperation($statusArr, $moduleId, $getStoreDetails['store_id']);
			}
			//Email template data
			$emailTempArr = (isset($settingsArray['template_data']) && !empty($settingsArray['template_data'])) ? $settingsArray['template_data'] : [];
			if (!empty($emailTempArr)) {
				$this->emailTempOperation($emailTempArr, $moduleId, $getStoreDetails['store_id']);
			}

			//Quotation Payment Setting
			$paymentMethodArr = (isset($settingsArray['payment_methods']) && !empty($settingsArray['payment_methods'])) ? $settingsArray['payment_methods'] : [];
			if (!empty($paymentMethodArr)) {
				$this->quotePaymentOperation($paymentMethodArr, $getStoreDetails['store_id']);
			}

			$tagsArr = (isset($settingDataArr['tags']) && !empty($settingDataArr['tags']))
				? $settingDataArr['tags'] : [];
			//Unset tags from setting data array
			unset($settingDataArr['tags']);

			if (!empty($tagsArr)) {
				$this->tagOperation($tagsArr, $moduleId, $getStoreDetails['store_id']);
			}
			if ($moduleId == 1) {
				//Upload company logo
				$companyLogo = do_upload(
					'company_logo',
					path('abs', 'quotation'),
					[],
					'string'
				);
				if ($companyLogo != '') {
					//delete old logo
					delete_file(path('abs', 'quotation') . $oldCompanyLogo);
					$settingDataArr['company_logo'] = $companyLogo;
				} else {
					$settingDataArr['company_logo'] = $oldCompanyLogo;
				}
				// For Shipping method
				if (isset($settingsArray['shipping_methods']) && !empty($settingsArray['shipping_methods'])) {
					$settingDataArr['shipping_methods'] = $settingsArray['shipping_methods'];
				}
				// For Tax values
				if (isset($settingsArray['tax_percent']) && !empty($settingsArray['tax_percent'])) {
					$settingDataArr['tax_percent'] = $settingsArray['tax_percent'];
				}
				// For quote display in my account section
				if (isset($settingsArray['is_show_dashboard_quotes']) && !empty($settingsArray['is_show_dashboard_quotes'])) {
					$settingDataArr['is_show_dashboard_quotes'] = $settingsArray['is_show_dashboard_quotes'];
				}
			}
			$dateFormateType = 24;
			foreach ($settingDataArr as $settingKey => $settingValue) {
				if ($moduleId == 4) {
					//Change the time to 24 formate
					if ($settingKey == 'time_format' && $settingValue == 12) {
						$dateFormateType = 12;
					}
					if ($dateFormateType == 12 && $settingKey == 'working_hours') {
						$workingHoursValue = $settingValue;
						$workingHours = [
							'starts_at' => date("H:i", strtotime($workingHoursValue['starts_at'])),
							'ends_at' => date("H:i", strtotime($workingHoursValue['ends_at']))
						];
						$settingValue = $workingHours;
					}
				}
				$settingsData = [
					'setting_key' => $settingKey,
					'setting_value' => json_encode($settingValue),
					'module_id' => $moduleId,
					'store_id' => $getStoreDetails['store_id'],
				];
				$saveSettingsData = new ProductionHubSetting($settingsData);
				if ($saveSettingsData->save()) {
					$settingLastInsertId = $saveSettingsData->xe_id;
				}
			}
			//Check if quote_id is changed or not
			if ($moduleId == 1 && !empty($oldQuoteId) && !empty($newQuoteId) && ($oldQuoteId != $newQuoteId)) {
				$settingInit->where(
					[
						'store_id' => $getStoreDetails['store_id'],
						'module_id' => $moduleId,
						'setting_key' => 'quote_id',
					]
				)->update(['flag' => '1']);
			}
			//Check if job_card is changed or not
			if ($moduleId == 4 && !empty($oldJobId) && !empty($newJobId) && ($oldJobId != $newJobId)) {
				$settingInit->where(
					[
						'store_id' => $getStoreDetails['store_id'],
						'module_id' => $moduleId,
						'setting_key' => 'job_card',
					]
				)->update(['flag' => '1']);
			}

			//Check if purchase_order_id is changed or not
			if ($moduleId == 3 && !empty($oldPOId) && !empty($newPOId) && ($oldPOId != $newPOId)) {
				$settingInit->where(
					[
						'store_id' => $getStoreDetails['store_id'],
						'module_id' => $moduleId,
						'setting_key' => 'purchase_order_id',
					]
				)->update(['flag' => '1']);
			}

			if (isset($settingLastInsertId) && $settingLastInsertId > 0) {
				$jsonResponse = [
					'status' => 1,
					'message' => message('Production Hub Setting', 'saved'),
				];
				$pluginsInit = new PluginSettings();
				$quickStatus = $pluginsInit->where('catalog_code', 'quickbooks')
					->where('status', 1);
				$pluginCountquick = $quickStatus->count();
				if ($pluginCountquick > 0) {
					$quickBookObj = new QuickBookController();
					$quickBookObj->quickbookCompanyCreateUpdate($settingDataArr);
				}
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Get old quote id from setting table
	 *
	 * @param $storeId Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   17 Apr 2019
	 * @return quote id array
	 */
	private function getOldQuoteId($storeId)
	{
		$settingInit = new ProductionHubSetting();
		$quoteIdRes = $settingInit->select('setting_key', 'setting_value')
			->where(
				[
					'store_id' => $storeId,
					'module_id' => 1,
				]
			)
			->where(
				function ($q) {
					$q->where('setting_key', 'quote_id')
						->orWhere('setting_key', 'company_logo');
				}
			);
		if ($quoteIdRes->count()) {
			$quoteArr = $quoteIdRes->get()->toArray();
			$resResult = [];
			foreach ($quoteArr as $quoteData) {
				if ($quoteData['setting_key'] == 'quote_id') {
					$newArr['quote_id'] = $quoteData['setting_value'];
				}
				if ($quoteData['setting_key'] == 'company_logo') {
					$newArr['company_logo'] = $quoteData['setting_value'];
				}
				if ($newArr['company_logo'] != '' && $newArr['quote_id'] != '') {
					array_push($resResult, $newArr);
				}
			}
			$resResult = $resResult[0];
		}
		return $resResult;
	}

	/**
	 * For Production Status Operation (Save, Update, delete)
	 *
	 * @param $statusArr Status data for save
	 * @param $moduleId  Module Id
	 * @param $storeId   Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   17 Apr 2019
	 * @return boolean
	 */
	private function statusOperation($statusArr, $moduleId, $storeId)
	{
		if (!empty($statusArr) && $moduleId != '' && $storeId != '') {
			$statusInit = new ProductionStatus();
			if ($moduleId == 3) {
				$statusInit = new PurchaseOrderStatus();
			}
			foreach ($statusArr as $order => $status) {
				//Update tags
				if ($status['id'] != 0) {
					//Get status data
					$statusDataArr = $statusInit
						->where(
							[
								'xe_id' => $status['id'],
								'module_id' => $moduleId,
								'store_id' => $storeId,
							]
						);
					if ($statusDataArr->count() > 0) {
						$statusData = $statusDataArr->get();
						$statusData = json_clean_decode($statusData, true);
						// $oldStatusName = $statusData[0]['status_name'];
						$oldStatusSlug = $statusData[0]['slug'];
					}
					$statusUpdateData = [
						'status_name' => $status['status_name'],
						'color_code' => $status['color_code'],
						'sort_order' => $order + 1,
					];
					if ($statusData[0]['slug'] == '_' && $statusData[0]['is_default'] == 0) {
						$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
						$charactersLength = strlen($characters);
						$randomString = '';
						for ($i = 0; $i < 15; $i++) {
							$randomString .= $characters[rand(0, $charactersLength - 1)];
						}
						$slug = $randomString;
						$statusUpdateData['slug'] = $slug;
					}
					$statusInit
						->where(
							[
								'xe_id' => $status['id'],
								'module_id' => $moduleId,
								'store_id' => $storeId,
							]
						)
						->update($statusUpdateData);
					$lastStatusId = $status['id'];
					if ($moduleId == 4) {
						//$oldTemplateTypeName = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '_', $oldStatusName)));
						$templateInit = new ProductionEmailTemplates();
						$tempDataArr = $templateInit->select('xe_id', 'template_name')
							->where(
								[
									'template_type_name' => $oldStatusSlug,
									'module_id' => $moduleId,
									'store_id' => $storeId,
								]
							);
						if ($tempDataArr->count() > 0) {
							//$newTemplateTypeName = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '_', $status['status_name'])));
							$tempData = $tempDataArr->get();
							$tempData = json_clean_decode($tempData, true);
							$oldTemplateTypeId = $tempData[0]['xe_id'];
							$oldTemplatename = $tempData[0]['template_name'];
							//update Template type name
							/*$updateData = [
								'template_type_name' => $newTemplateTypeName,
							];*/
							if ($oldTemplatename == '') {
								$updateData['template_name'] = $status['status_name'];
								$templateInit
									->where(
										[
											'xe_id' => $oldTemplateTypeId,
											'module_id' => $moduleId,
											'store_id' => $storeId,
										]
									)
									->update($updateData);
							}
						}
						/*update barode table*/
						$statusName = "Mark job status " . strtolower($status['status_name']) . ' as Done';
						$this->updateBarCodeStatusName($moduleId, $status['id'], $statusName, $storeId);
					}
				} else {
					$slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '_', $status['status_name'])));
					if ($slug == '_') {
						$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
						$charactersLength = strlen($characters);
						$randomString = '';
						for ($i = 0; $i < 15; $i++) {
							$randomString .= $characters[rand(0, $charactersLength - 1)];
						}
						$slug = $randomString;
					}
					$statusData = [
						'status_name' => $status['status_name'],
						'color_code' => $status['color_code'],
						'sort_order' => $order + 1,
						'module_id' => $moduleId,
						'is_default' => ($status['is_default'] == 0) ? '0' : '1',
						'store_id' => $storeId,
						'slug' => $slug,
					];
					$lastStatusId = $this->saveStatusData($statusData, $moduleId);
					if ($moduleId == 4) {
						// Create barcode for production status
						$isArray = 1;
						$statusName = "Mark job status " . strtolower($status['status_name']) . ' as Done';
						$this->barcodeGenerate($moduleId = 4, $storeId, $statusName, $slug, $isArray);

						//Dynamically create email template
						$templateData = [
							'store_id' => $storeId,
							'template_type_name' => $slug,
							'template_name' => $status['status_name'],
							'module_id' => 4,
						];
						$template = new ProductionEmailTemplates($templateData);
						$template->save();
					}
				}
				if ($moduleId == 4) {
					if (!empty($status['print_profiles'])) {
						$printProfileRelInit = new StatusPrintProfileRel();
						$printProfileRelInit->where(['status_id' => $lastStatusId])->delete();
						foreach ($status['print_profiles'] as $profileValue) {
							$printProfileRelInit->insert(['status_id' => $lastStatusId, 'print_profile_id' => $profileValue]);
						}
					}

					if (!empty($status['assignee_id'])) {
						$assigneeRelInit = new StatusAssigneeRel();
						$assigneeRelInit->where(['status_id' => $lastStatusId])->delete();
						foreach ($status['assignee_id'] as $assigneeValue) {
							$assigneeRelInit->insert(['status_id' => $lastStatusId, 'assignee_id' => $assigneeValue]);
						}
					}

					if ($status['is_global'] == 1) {
						$printProfileRelInit = new StatusPrintProfileRel();
						$assigneeRelInit = new StatusAssigneeRel();
						$printProfileRelInit->where(['status_id' => $lastStatusId])->delete();
						//$assigneeRelInit->where(['status_id' => $status['id']])->delete();
					}
					$statusFeatureInit = new StatusFeatures();
					$statusFeatureInit->where(['status_id' => $lastStatusId])->delete();
					$statusFeatureInit->insert(
						[
							'status_id' => $lastStatusId,
							'duration' => !empty($status['duration']) ? $status['duration'] : "",
							'is_global' => !empty($status['is_global']) ? $status['is_global'] : 0,
							'is_group' => (!empty($status['is_group']) && $status['is_group'] == 1) ? 1 : 0,
						]
					);
				}
			}
			return true;
		}
	}

	/**
	 * For Production Tag Operation (Save, Update, delete)
	 *
	 * @param $tagsArr  Tags data for save
	 * @param $moduleId Module Id
	 * @param $storeId  Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   17 Apr 2019
	 * @return boolean
	 */
	private function tagOperation($tagsArr, $moduleId, $storeId)
	{
		if (!empty($tagsArr) && $moduleId != '' && $storeId != '') {
			//Delete tags and tag relations
			$tagInit = new ProductionTags();
			$oldTags = $tagInit->select('xe_id')
				->where('module_id', $moduleId)->where('store_id', $storeId);
			if ($oldTags->count() > 0) {
				$oldTagsArr = $oldTags->get()->toArray();
				//Get all tag id from tag table
				$oldTagIds = array_column($oldTagsArr, 'xe_id');
				$newTagIds = array_column($tagsArr, 'id');
				$deleteTagIds = array_diff($oldTagIds, $newTagIds);
				if ($tagInit->whereIn('xe_id', $deleteTagIds)->delete() && ($moduleId == 1)) {
					//Delete from quote tag relation
					DB::table('quote_tag_rel')
						->whereIn('tag_id', $deleteTagIds)
						->delete();
				}
			}
			foreach ($tagsArr as $tags) {
				//Update tags
				if ($tags['id'] != 0) {
					$tagInit->where(['xe_id' => $tags['id'], 'module_id' => $moduleId, 'store_id' => $storeId])
						->update(['name' => $tags['name']]);
				} else {
					$tagData = [
						'name' => $tags['name'],
						'module_id' => $moduleId,
						'store_id' => $storeId,
					];
					$this->saveTagsData($tagData);
				}
			}
			return true;
		}
		return false;
	}

	/**
	 * GET: Production Hub Setting
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $otherParameter Other perameter
	 *
	 * @author debashrib@riaxe.com
	 * @date   02 Apr 2019
	 * @return json response
	 */
	public function getProductionSetting($request, $response, $otherParameter = [])
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Production Hub Setting', 'error'),
		];
		$getStoreDetails = get_store_details($request);
		$moduleId = !empty($request->getQueryParam('module_id')) ? $request->getQueryParam('module_id') : $otherParameter['module_id'];
		$isAdmin = !empty($request->getQueryParam('admin_view')) ? $request->getQueryParam('admin_view') : 0;
		$productionSettingInit = new ProductionHubSetting();
		$getProductionSetting = $productionSettingInit
			->where('store_id', $getStoreDetails['store_id']);
		if (isset($moduleId) && $moduleId != '') {
			$getProductionSetting->where('module_id', $moduleId);
		}
		$settings = [];
		if ($getProductionSetting->count() > 0) {
			$getSettingData = $getProductionSetting->get();
			$settings = [];
			$dateFormateType = 24;
			foreach ($getSettingData as $settingValue) {
				if ($moduleId == 4) {
					if ($settingValue['setting_key'] == 'time_format' && $settingValue['setting_value'] == 12) {
						$dateFormateType = 12;
					}

					if ($dateFormateType == 12 && $settingValue['setting_key'] == 'working_hours') {
						$workingHoursValue = $settingValue['setting_value'];
						$workingHoursValue = json_clean_decode($workingHoursValue, true);
						$workingHours = [
							'starts_at' => date("g:i A", strtotime($workingHoursValue['starts_at'])),
							'ends_at' => date("g:i A", strtotime($workingHoursValue['ends_at']))
						];
						$settingValue['setting_value'] = json_clean_encode($workingHours);
					}
				}
				$settings[$settingValue['setting_key']] = json_clean_decode(
					$settingValue['setting_value'],
					true
				);
			}
		}
		if (!empty($moduleId)) {
			//Get tags data
			$tagsData = [];
			$tagInit = new ProductionTags();
			$tagsArr = $tagInit->select('xe_id as id', 'name')
				->where(
					[
						'module_id' => $moduleId,
						'store_id' => $getStoreDetails['store_id'],
					]
				);
			if ($tagsArr->count() > 0) {
				$tagsData = $tagsArr->get();
			}
			$settings['tags'] = $tagsData;
			//Get Status data
			if (isset($moduleId) && $moduleId != 3) {
				$statusInit = new ProductionStatus();
				$statusArr = $statusInit
					->select('xe_id as id', 'status_name', 'color_code', 'is_default', 'slug')
					->where(
						[
							'module_id' => $moduleId,
							'store_id' => $getStoreDetails['store_id'],
						]
					)->orderBy('sort_order', 'ASC');
			}
			if (isset($moduleId) && $moduleId == 3) {
				$statusInit = new PurchaseOrderStatus();
				$statusArr = $statusInit
					->select('xe_id as id', 'status_name', 'color_code', 'is_default')
					->where(
						[
							'module_id' => $moduleId,
							'store_id' => $getStoreDetails['store_id'],
						]
					)->orderBy('sort_order', 'ASC');
			}
			if ($statusArr->count() > 0) {
				$statusData = $statusArr->get();
				$statusDetails = $statusData->toArray();
				if ($moduleId == 4) {
					foreach ($statusDetails as $statusKey => $statusValue) {
						$printProfileRelInit = new StatusPrintProfileRel();
						$profRelValue = $printProfileRelInit
							->select('print_profile_id')
							->where(
								[
									'status_id' => $statusValue['id'],
								]
							)->get();
						$statusDetails[$statusKey]['print_profiles'] = [];
						if (!empty($profRelValue)) {
							foreach ($profRelValue->toArray() as $relKey => $profRelValue) {
								$statusDetails[$statusKey]['print_profiles'][$relKey] = $profRelValue['print_profile_id'];
							}
						}
						$assigneeRelInit = new StatusAssigneeRel();
						$assigneeRelValue = $assigneeRelInit
							->select('assignee_id')
							->where(
								[
									'status_id' => $statusValue['id'],
								]
							)->get();
						$statusDetails[$statusKey]['assignee_id'] = [];
						if (!empty($assigneeRelValue)) {
							foreach ($assigneeRelValue->toArray() as $relKey => $assigneeRelValue) {
								$statusDetails[$statusKey]['assignee_id'][$relKey] = $assigneeRelValue['assignee_id'];
							}
						}

						$statusFeatureInit = new StatusFeatures();
						$featureValue = $statusFeatureInit
							->select('duration', 'is_global', 'is_group')
							->where(
								[
									'status_id' => $statusValue['id'],
								]
							)->first();

						if (!empty($featureValue)) {
							$statusDetails[$statusKey]['duration'] = $featureValue->duration;
							$statusDetails[$statusKey]['is_global'] = $featureValue->is_global;
							$statusDetails[$statusKey]['is_group'] = $featureValue->is_group;
						}
					}
				}
				$settings['status'] = $statusDetails;
			}
			if ($moduleId == 4) {
				//Get holiday list
				$productionJobHolidaysInit = new ProductionJobHolidays();
				$holidays = $productionJobHolidaysInit->where('store_id', $getStoreDetails['store_id']);
				$getHolidays = $holidays->get();
				$getHolidays = json_clean_decode($getHolidays, true);
				$settings['holiday_list'] = $getHolidays;
			}
			// Get Email Template Data
			if ($moduleId == 1 || $moduleId == 4 || $moduleId == 6 || $moduleId == 2 || $moduleId == 3 || $moduleId == 7) {
				$getAllOrderStatus = [];
				if ($moduleId == 2) {
					$ordersControllerInit = new OrdersController();
					$getAllOrderStatus = $ordersControllerInit->getAllOrderStatus($request, $response, ['return_type' => 1]);
				}
				$settings['template_data'] = $this->getEmailTemplate($moduleId, $getStoreDetails, '', $getAllOrderStatus);
			}

			if ($moduleId == 1) {
				// Company Logo
				$companyLogo = $settings['company_logo'];
				$settings['company_logo'] = path('read', 'quotation') . $companyLogo;
				// Get Payment Methods
				$settings['payment_methods'] = $this->getPaymentMethod($getStoreDetails['store_id'], $isAdmin);
				/*check payment status*/
				$isSelected = 1;
				$selectedIndex = array_search($isSelected, array_column($settings['payment_methods'], 'is_selected'));
				$activePaymentMethodData =  $settings['payment_methods'][$selectedIndex]['payment_setting'];
				$isPaymentStatus = false;
				if (!empty($activePaymentMethodData)) {
					foreach ($activePaymentMethodData as $key => $value) {
						if (!empty($value)) {
							$isPaymentStatus = true;
						}
					}
				}
				$settings['payment_methods_status'] = $isPaymentStatus;
			}
		}

		$jsonResponse = [
			'status' => 1,
			'data' => $settings,
		];
		if (!empty($otherParameter) && $otherParameter['return_type'] == 1) {
			return $jsonResponse;
		}
		$strType = ($moduleId == 1) ? 1 : 0;
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode],
			$strType
		);
	}

	/**
	 * GET: Production Hub Modules
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   24 mar 2019
	 * @return json response
	 */
	public function getProductionModule($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Production Hub Module', 'error'),
		];
		$productionModuleInit = new ProductionHubModule();
		$getProductionModule = $productionModuleInit->get();

		if (!empty($getProductionModule)) {
			$jsonResponse = [
				'status' => 1,
				'data' => $getProductionModule,
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * GET: Quotation Email Template Abbriviation
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   04 June 2019
	 * @return json response
	 */
	public function getEmailAbbriviation($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Abbriviation', 'not_found'),
		];
		$moduleId = $request->getQueryParam('module_id');
		$isShowPrice = !empty($request->getQueryParam('show_price')) ? $request->getQueryParam('show_price') : 1;
		$abbrivationsInit = new ProductionAbbriviations();
		$getAbbrivations = $abbrivationsInit->where('module_id', $moduleId);
		if ($moduleId == 2 && $isShowPrice == 0) {
			$getAbbrivations->where('abbr_name', '!=', '{order_value}');
		}
		if ($getAbbrivations->count() > 0) {
			$getAbbrivations = $getAbbrivations->get();
			$jsonResponse = [
				'status' => 1,
				'data' => $getAbbrivations,
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Get Quotation email Template Data
	 *
	 * @param $moduleId        Module Id
	 * @param $getStoreDetails store details
	 * @param $emailType       email type
	 *
	 * @author debashrib@riaxe.com
	 * @date   04 June 2019
	 * @return array response
	 */
	public function getEmailTemplate($moduleId, $getStoreDetails, $emailType = '', $orderStatus = [])
	{
		$emailTempInit = new ProductionEmailTemplates();
		$emailTempDataArr = [];
		$emailTempData = $emailTempInit->select('xe_id', 'template_type_name', 'subject', 'message', 'is_configured', 'template_name as display_temp_name');
		if ($emailTempData->count() > 0) {
			$templateDataArr = $emailTempData->where(['module_id' => $moduleId, 'store_id' => $getStoreDetails['store_id']]);
			if (isset($emailType) && $emailType != '') {
				$templateDataArr = $templateDataArr->where('template_type_name', $emailType);
			}
			$templateDataArr = $templateDataArr->get();
			$templateDataArr = json_clean_decode($templateDataArr, true);
			//condition added for fixing release 402
			if (($moduleId == 2 || $moduleId == 6) && empty($templateDataArr)) {
				$templateDataArr = $emailTempInit->where(['module_id' => $moduleId, 'store_id' => 0]);
				if (isset($emailType) && $emailType != '') {
					$templateDataArr = $templateDataArr->where('template_type_name', $emailType);
				}
				$templateDataArr = $templateDataArr->get();
				$templateDataArr = json_clean_decode($templateDataArr, true);
			}
			foreach ($templateDataArr as $templateData) {
				$tempData = $templateData;
				$tempData['subject'] = ($templateData['subject'] == null) ? '' : $templateData['subject'];
				$tempData['message'] = ($templateData['message'] == null) ? '' : $templateData['message'];
				if ($moduleId == 2 && !empty($orderStatus)) {
					$tempType = $templateData['template_type_name'];
					$statusTemplate = array_filter($orderStatus, function ($item) use ($tempType) {
						return $item['key'] == $tempType;
					});
					$statusTemplate = $statusTemplate[array_keys($statusTemplate)[0]];
					$tempData['template_name'] = $statusTemplate['value'];
				}
				$tempData['display_temp_name'] = ($templateData['display_temp_name'] == null) ? '' : $templateData['display_temp_name'];
				array_push($emailTempDataArr, $tempData);
			}
			//For order status email template
			if ($moduleId == 2 && !empty($orderStatus)) {
				foreach ($orderStatus as $status) {
					$statusSlug = $status['key'];
					$statusName = $status['value'];
					$statusTemplate = array_filter($templateDataArr, function ($item) use ($statusSlug) {
						return $item['template_type_name'] == $statusSlug;
					});
					$statusTemplate = $statusTemplate[array_keys($statusTemplate)[0]];
					if (empty($statusTemplate)) {
						$tempStatusData = [
							'xe_id' => 0,
							'template_type_name' => $statusSlug,
							'subject' => '',
							'message' => '',
							'is_configured' => 0,
							'template_name' => $statusName
						];
						array_push($emailTempDataArr, $tempStatusData);
					}
				}
			}
		}
		return $emailTempDataArr;
	}

	/**
	 * For Quotation Email template
	 *
	 * @param $tempArr  template data
	 * @param $moduleId Module Id
	 * @param $storeId  Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   06 June 2019
	 * @return boolean
	 */
	private function emailTempOperation($tempArr, $moduleId, $storeId)
	{
		if (!empty($tempArr) && $storeId != '') {
			$emailTempInit = new ProductionEmailTemplates();
			foreach ($tempArr as $template) {
				if (isset($template['is_configured'])) {
					if ($template['is_configured'] == 0) {
						$isConfigured = '0';
					} else {
						$isConfigured = '1';
					}
				} else {
					if ($template['subject'] != '' && $template['message'] != '') {
						$isConfigured = '1';
					} else {
						$isConfigured = '0';
					}
				}
				//Update Status
				$emailTempInit
					->where(
						[
							'xe_id' => $template['xe_id'],
							'template_type_name' => $template['template_type_name'],
							'module_id' => $moduleId,
						]
					)
					->update(
						[
							'store_id' => $storeId,
							'subject' => $template['subject'],
							'message' => $template['message'],
							'is_configured' => $isConfigured,
						]
					);
			}
			return true;
		}
	}

	/**
	 * Get Quotation Payment Method Data
	 *
	 * @author debashrib@riaxe.com
	 * @date   08 June 2019
	 * @return array response
	 */
	public function getPaymentMethod($storeId = 1, $isAdmin = 0, $isAsterisks = 1)
	{
		$asterisks = "XXXXXXXXXXXXXXXXXXX";
		$paymentMethodInit = new QuotationPaymentMethods();
		$paymentSettingInit = new QuotationPaymentSettings();
		$paymentSettingArr = [];
		$paymentMethodData = $paymentMethodInit->where('store_id', $storeId);
		if ($paymentMethodData->count() > 0) {
			$paymentMethodArr = $paymentMethodData->get();
			$paymentMethodArr = json_clean_decode($paymentMethodArr, true);
			$paymentSettingDataArr = [];
			foreach ($paymentMethodArr as $paymentMethod) {
				$newSettingData = $paymentMethod;
				$paymentSetting = $paymentSettingInit->where('payment_method_id', $paymentMethod['xe_id']);
				$settings = [];
				if ($paymentSetting->count() > 0) {
					$paymentSettingArr = $paymentSetting->get();
					foreach ($paymentSettingArr as $paymentSettingData) {
						if ($isAdmin == 1) {
							$stringSecret = '';
							if (!empty($paymentSettingData['keyvalue'])) {
								if ($isAsterisks == 1) {
									$decryptString =  $this->decryptKey($paymentSettingData['keyvalue']);
									$firstNCharacters =  $this->getFirstNCharacters($decryptString, 3);
									$lastNCharacters = $this->getLastNCharacters($decryptString, 4);
									$stringSecret = $firstNCharacters . '_' . $asterisks . '_' . $lastNCharacters;
								} else {
									$stringSecret = $paymentSettingData['keyvalue'];
								}
							}
							$settings[$paymentSettingData['keyname']] = (empty($stringSecret)) ?  $paymentSettingData['keyvalue'] : $stringSecret;
						} else {
							if ($paymentSettingData['keyname'] != 'secret_key' && $paymentSettingData['keyname'] != 'merchant_email_id') {
								$settings[$paymentSettingData['keyname']] = ($paymentSettingData['keyvalue'] != '') ? $paymentSettingData['keyvalue'] : '';
							}
						}
					}
				}
				$newSettingData['payment_setting'] = $settings;
				array_push($paymentSettingDataArr, $newSettingData);
			}
		}
		return $paymentSettingDataArr;
	}

	/**
	 * For Quotation Payment Method
	 *
	 * @param $paymentMethodArr Payment Method data
	 * @param $storeId          Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   08 June 2019
	 * @return boolean
	 */
	private function quotePaymentOperation($paymentMethodArr, $storeId)
	{
		if (!empty($paymentMethodArr) && $storeId != '') {
			$paymentMethodInit = new QuotationPaymentMethods();
			$paymentSettingInit = new QuotationPaymentSettings();
			foreach ($paymentMethodArr as $paymentMethod) {
				//Update Status
				$paymentMethodInit
					->where(
						[
							'xe_id' => $paymentMethod['xe_id'],
							'payment_type' => $paymentMethod['payment_type'],
						]
					)
					->update(
						[
							'payment_mode' => $paymentMethod['payment_mode'],
							'is_selected' => $paymentMethod['is_selected'],
						]
					);
				//Delete data frpm payment setting table
				$paymentSettingInit->where(
					'payment_method_id',
					$paymentMethod['xe_id']
				)->delete();
				$paymentSettingDataArr = $paymentMethod['payment_setting'];

				foreach ($paymentSettingDataArr as $keyname => $paymentSettingData) {
					$saveData = [
						'payment_method_id' => $paymentMethod['xe_id'],
						'keyname' => $keyname,
						'keyvalue' => (!empty($paymentSettingData)) ? $this->encryptKey($paymentSettingData) : '',
					];
					$savePaymentSetting = new QuotationPaymentSettings($saveData);
					$savePaymentSetting->save();
				}
			}
			return true;
		}
	}

	/**
	 * Automate Language File
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author satyabratap@riaxe.com
	 * @date   17 Aug 2020
	 * @return boolean
	 */
	public function modifyJson($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Upgrade Json', 'error'),
		];
		$modifiedAssetsPath = rtrim(RELATIVE_PATH, WORKING_DIR) . '/' . 'modified_assets/';
		$newAssetsPath = scandir($modifiedAssetsPath);
		if (!empty($newAssetsPath)) {
			foreach ($newAssetsPath as $newFolderValue) {
				if ($newFolderValue == 'languages') {
					$newLanguagePath = $modifiedAssetsPath . 'languages/';
					$newLanguageFolders = scandir($newLanguagePath);
					$oldLanguageFolders = scandir(path('abs', 'language'));
					if (!empty($newLanguageFolders)) {
						$diffFolders = array_diff($newLanguageFolders, $oldLanguageFolders);
						if (!empty($diffFolders)) {
							foreach ($diffFolders as $diffKey => $languageDiff) {
								unset($newLanguageFolders[$diffKey]);
								copy($newLanguagePath . $languageDiff, path('abs', 'language') . $languageDiff);
							}
						}
						foreach ($newLanguageFolders as $folder) {
							if (!is_dir($folder)) {
								$oldLanguageFiles = scandir(path('abs', 'language') . $folder);
								$newLanguageFiles = scandir($newLanguagePath . $folder);
								if (!empty($newLanguageFiles)) {
									$newFileArray = array_diff($newLanguageFiles, $oldLanguageFiles);
									foreach ($newFileArray as $fileKey => $files) {
										unset($newLanguageFiles[$fileKey]);
										copy($newLanguagePath . $folder . '/' . $files, path('abs', 'language') . $folder . '/' . $files);
									}
									foreach ($newLanguageFiles as $newFileName) {
										if (strpos($newFileName, ".json") !== false) {
											$oldContent = read_file(path('abs', 'language') . $folder . '/' . $newFileName);
											$newContent = read_file($newLanguagePath . $folder . '/' . $newFileName);
											$oldArrayContent = json_clean_decode($oldContent, true);
											$newArrayContent = json_clean_decode($newContent, true);
											if ($folder == 'admin') {
												foreach ($oldArrayContent as $oldLangKey => $langValue) {
													foreach ($langValue as $key => $value) {
														if (strpos($value, '<p>') !== false || strpos($value, '</p>') !== false) {
															$value = str_replace('</p>', '', $value);
															$value = str_replace("<p class='mb-1'>", '<p>', $value);
															$tagArray = explode('<p>', $value);
															foreach ($tagArray as $tagKey => $tagValue) {
																if (!empty($tagValue)) {
																	if ($tagKey == 1) {
																		$oldArrayContent[$oldLangKey][$key] = $tagValue;
																	} else {
																		$oldArrayContent[$oldLangKey][$key . $tagKey] = $tagValue;
																	}
																}
															}
														}
													}
												}
											}

											foreach ($newArrayContent as $newLangKey => $langValue) {
												if (!isset($oldArrayContent[$newLangKey])) {
													$oldArrayContent[$newLangKey] = $newArrayContent[$newLangKey];
												} else {
													$diffArrayValue = array_diff_key($newArrayContent[$newLangKey], $oldArrayContent[$newLangKey]);
													foreach ($diffArrayValue as $newKey => $newValue) {
														$oldArrayContent[$newLangKey][$newKey] = $newValue;
													}
												}
											}
											$finalContent = json_clean_encode($oldArrayContent);
											write_file(path('abs', 'language') . $folder . '/' . $newFileName, $finalContent);
										}
									}
								}
							}
						}
					}
				}
				if ($newFolderValue == 'settings') {
					$newSettingPath = $modifiedAssetsPath . 'settings/stores/1';
					$newSettingFolders = scandir($newSettingPath);

					if (!empty($newSettingFolders)) {
						foreach ($newSettingFolders as $settingsFile) {
							if (strpos($settingsFile, "settings.json") !== false) {
								$oldSettingsContent = read_file(path('abs', 'setting') . 'stores/1/' . $settingsFile);
								$newSettingsContent = read_file($newSettingPath . '/' . $settingsFile);
								$oldSettingsArray = json_clean_decode($oldSettingsContent, true);
								$newSettingsArray = json_clean_decode($newSettingsContent, true);
								foreach ($newSettingsArray as $newSettingsKey => $settingsValue) {
									if (is_array($newSettingsArray[$newSettingsKey])) {
										foreach ($settingsValue as $innerKey => $innerValue) {
											if (!isset($oldSettingsArray[$newSettingsKey][$innerKey])) {
												$oldSettingsArray[$newSettingsKey][$innerKey] = $newSettingsArray[$newSettingsKey][$innerKey];
											}
										}
									} else {
										if (!isset($oldSettingsArray[$newSettingsKey])) {
											$oldSettingsArray[$newSettingsKey] = $newSettingsArray[$newSettingsKey];
										}
									}
								}
								$finalContent = json_clean_encode($oldSettingsArray);
								write_file(path('abs', 'setting') . 'stores/1/' . $settingsFile, $finalContent);
							}
							if (strpos($settingsFile, "currencies.json") !== false) {
								$newCurrencyContent = read_file($newSettingPath . '/' . $settingsFile);
								write_file(path('abs', 'setting') . 'stores/1/' . $settingsFile, $newCurrencyContent);
							}
						}
					}
				}
			}
			$jsonResponse = [
				'status' => 1,
				'message' => message('Json Updation', 'done'),
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Update total used key of assets on order
	 *
	 * @param $customDesignId Store Id
	 *
	 * @author satyabratap@riaxe.com
	 * @date   24 Aug 2020
	 * @return Boolean
	 */
	public function updateMostusedAssets($customDesignId)
	{
		$jsonPath = path('abs', 'design_state') . 'carts/' . $customDesignId . '.json';
		$jsonContent = file_get_contents($jsonPath);
		$arrayContent = json_clean_decode($jsonContent, true);
		if (!empty($arrayContent['used_cliparts'])) {
			foreach ($arrayContent['used_cliparts'] as $clipartId) {
				$cliaprtInit = new Clipart();
				$cliaprt = $cliaprtInit->select('total_used')->where('xe_id', $clipartId)->first();
				$cliaprtInit->where('xe_id', $clipartId)->update(['total_used' => $cliaprt->total_used + 1]);
			}
		}
		if (!empty($arrayContent['used_fonts'])) {
			foreach ($arrayContent['used_fonts'] as $fontkey => $fontId) {
				$fontInit = new Font();
				$font = $fontInit->select('total_used')->where('xe_id', $fontId)->first();
				$fontInit->where('xe_id', $fontId)->update(['total_used' => $font->total_used + 1]);
			}
		}
	}
	/**
	 * POST: Save Email Setting
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author soumays@riaxe.com
	 * @date   22 September 2019
	 * @return json response wheather data is saved or any error occured
	 */
	public function saveEmailSettings($request, $response)
	{
		$getStoreDetails = get_store_details($request);
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Email Setting', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		if (isset($allPostPutVars['settings']) && $allPostPutVars['settings'] != "") {
			$settingsArray = json_clean_decode($allPostPutVars['settings'], true);
			foreach ($settingsArray as $templateType) {
				if (!empty($templateType['template_data'])) {
					foreach ($templateType['template_data'] as $templateData) {
						if ($templateData['xe_id'] > 0) {
							/* update data */
							$emailTempInit = new ProductionEmailTemplates();
							$emailTempInit
								->where(
									[
										'xe_id' => $templateData['xe_id'],
										'module_id' => $templateType['module_id'],
									]
								)
								->update(
									[
										'store_id' => $getStoreDetails['store_id'],
										'template_type_name' => ($templateType['module_id'] == 2) ? $templateData['template_type_name'] : trim(strtolower(preg_replace('/\s+/', '_', $templateData['template_type_name']))),
										'subject' => $templateData['subject'],
										'message' => $templateData['message'],
										'is_configured' => ($templateData['subject'] != '' && $templateData['message'] != '') ? '1' : '0',
									]
								);
						} else {
							/* insret data */
							$saveData = [
								'store_id' => $getStoreDetails['store_id'],
								'template_type_name' => ($templateType['module_id'] == 2) ? $templateData['template_type_name'] : trim(strtolower(preg_replace('/\s+/', '_', $templateData['template_type_name']))),
								'subject' => $templateData['subject'],
								'message' => $templateData['message'],
								'is_configured' => ($templateData['subject'] != '' && $templateData['message'] != '') ? '1' : '0',
								'module_id' => $templateType['module_id'],

							];
							$emailTempInitSave = new ProductionEmailTemplates($saveData);
							$emailTempInitSave->save();
						}
					}
				}
			}
			$jsonResponse = [
				'status' => 1,
				'message' => message('Email Setting', 'saved'),
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}
	/**
	 * GET:Customer abbriviation values
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author soumya@riaxe.com
	 * @date   28 September 2020
	 * @return Json
	 */
	public function deleteCustomerEmailTemplate($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Delete email template ', 'error'),
		];
		if (isset($args) && !empty($args)) {
			$templateId = $args['id'];
			$emailTempInit = new ProductionEmailTemplates();
			$emailTemplateId = $emailTempInit->whereIn('xe_id', [$templateId])->count();
			if ($emailTemplateId > 0) {
				$status = $emailTempInit->where('xe_id', $templateId)->delete();
				if ($status) {
					$jsonResponse = [
						'status' => 1,
						'message' => 'Deleted successfully',
					];
				} else {
					$jsonResponse = [
						'status' => 0,
						'message' => 'No data deleted',
					];
				}
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Get the color Hex code from json.
	 *
	 * @param $colorDetail Color Name
	 *
	 * @author mukeshp@riaxe.com
	 * @date   08 Oct 2020
	 * @return string
	 */
	public function getColorSwatchValue($colorName)
	{
		$colorValue = "";
		if (!empty($colorName)) {
			$filePath = COLOR_SWATCH_JSON_URL;
			$data = fileGetContentsCurl($filePath);
			$colorData = json_decode($data, true);
			if (is_array($colorData)) {
				$colorArray = array_change_key_case($colorData, CASE_LOWER);
				$key = strtolower($colorName);
				$colorValue = isset($colorArray[$key]) ? $colorArray[$key] : "";
			}
		}
		return $colorValue;
	}

	/**
	 * GET: ImprintNext latest version details
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author robert@imprintnext.com
	 * @date   05 Oct 2020
	 * @return json response
	 */
	public function getLatestVersion($request, $response)
	{
		$currentVersion = $request->getQueryParam('current_version');
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => 'No data found',
		];
		if (isset($_SERVER['HTTP_HOST'])) {
			$host = $_SERVER['HTTP_HOST'];
		} elseif (isset($_SERVER['SERVER_NAME'])) {
			$host = $_SERVER['SERVER_NAME'];
		} else {
			$host = '';
		}
		$host = str_replace("www.", "", $host);
		$url = 'http://imprintnext.com/license_check/get_latest_version.php';
		if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off') {
			$url = 'https://imprintnext.com/license_check/get_latest_version.php';
		}
		$params = array(
			"current_version" => base64_encode($currentVersion),
			"domain_name" => base64_encode($host),
		);
		if (!empty($params) && is_array($params)) {
			$url .= '?' . http_build_query($params);
		}
		if (isset($currentVersion) && $currentVersion != '') {
			$returnData = call_simple_curl($url);
			$latestVersion = $releaseNotes = '';
			if (!empty($returnData)) {
				if ($returnData['status'] == 'success') {
					$latestVersion = $returnData['latest_version'];
					$releaseNotes = $returnData['release_notes'];
					$sameVersionAsCurrent = $returnData['send_current'];
					$data = [
						'next_version' => $latestVersion,
						'release_note' => $releaseNotes,
						'send_current' => $sameVersionAsCurrent,
					];
					$jsonResponse = [
						'data' => $data,
						'status' => 1,
					];
				} else {
					$jsonResponse = [
						'message' => $returnData['message'],
						'status' => 0,
					];
				}
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * GET: Language JSON
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author robert@imprintnext.com
	 * @date   05 Oct 2020
	 * @return JSON
	 */
	public function getAdminLanguage($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Language', 'not_found'),
		];
		$type = 'admin';
		// Get Store Specific Details from helper
		$getStoreDetails = get_store_details($request);
		$languageInit = new Language();
		$getLanguages = $languageInit->where('type', '=', $type);
		$finalData['data'] = $getLanguages->where(
			['store_id' => $getStoreDetails['store_id']]
		)
			->orderBy('xe_id', 'asc')
			->get();
		if ($languageInit->count() > 0) {
			$jsonResponse = [
				'status' => 1,
				'data' => $finalData['data'],
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Save data to email log after sending email
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   30 Nov 2020
	 * @return JSON
	 */
	public function saveDataForEmailLog($emailLog)
	{
		$lastInsertId = 0;
		if (!empty($emailLog)) {
			$emailLogData = new EmailLog($emailLog);
			if ($emailLogData->save()) {
				$lastInsertId = $emailLogData->xe_id;
			}
		}
		return $lastInsertId;
	}

	/**
	 * Update data to email log after sending email
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   11 Dec 2020
	 * @return JSON
	 */
	public function updateDataForEmailLog($emailLog)
	{
		$lastInsertId = 0;
		if (!empty($emailLog)) {
			$emailLogId = $emailLog['email_log_id'];
			$emailLogInit = new EmailLog();
			$getEmailLog = $emailLogInit->select('subject', 'message', 'success_email', 'failure_email', 'skipped_email')
				->where('xe_id', $emailLogId);
			if ($getEmailLog->count() > 0) {
				$getEmailLogData = $getEmailLog->first();
				$getEmailLogData = json_clean_decode($getEmailLogData, true);
				if ($emailLog['success_email'] != '') {
					$updateSuccessEmail = ($getEmailLogData['success_email'] != '') ? $getEmailLogData['success_email'] . ',' . $emailLog['success_email'] : $emailLog['success_email'];
				} else {
					$updateSuccessEmail = $getEmailLogData['success_email'];
				}
				if ($emailLog['failure_email'] != '') {
					$updateFailureEmail = ($getEmailLogData['failure_email'] != '') ? $getEmailLogData['failure_email'] . ',' . $emailLog['failure_email'] : $emailLog['failure_email'];
				} else {
					$updateFailureEmail = $getEmailLogData['failure_email'];
				}
				if ($emailLog['skipped_email'] != '') {
					$updateSkippedEmail = ($getEmailLogData['skipped_email'] != '') ? $getEmailLogData['skipped_email'] . ',' . $emailLog['skipped_email'] : $emailLog['skipped_email'];
				} else {
					$updateSkippedEmail = $getEmailLogData['skipped_email'];
				}
				$updateData = [
					'success_email' => $updateSuccessEmail,
					'failure_email' => $updateFailureEmail,
					'skipped_email' => $updateSkippedEmail,
				];
				if ($getEmailLogData['subject'] == '' && $getEmailLogData['message'] == '') {
					$updateData += [
						'subject' => $emailLog['subject'],
						'message' => $emailLog['message'],
					];
				}
				$emailLogInit->where('xe_id', $emailLogId)
					->update($updateData);
				$lastInsertId = $emailLogId;
			}
		}
		return $lastInsertId;
	}

	/**
	 * GET: Email Log Data
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   30 Nov 2020
	 * @return JSON
	 */
	public function getDataForEmailLog($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 1,
			'message' => message('Email Log', 'not_found'),
			'data' => [],
		];
		$getStoreDetails = get_store_details($request);
		$page = $request->getQueryParam('page');
		$perpage = $request->getQueryParam('perpage');
		$module = $request->getQueryParam('module');
		$emailLogInit = new EmailLog();
		$emailLog = $emailLogInit->where([
			'store_id' => $getStoreDetails['store_id'],
			'module' => $module,
		]);
		$getTotalPerFilters = $emailLog->count();
		$offset = 0;
		if (isset($page) && $page != "") {
			$totalItem = empty($perpage) ? PAGINATION_MAX_ROW : $perpage;
			$offset = $totalItem * ($page - 1);
			$emailLog->skip($offset)->take($totalItem);
		}
		$emailLog->orderBy('xe_id', 'DESC');
		if ($getTotalPerFilters > 0) {
			$emailLogData = $emailLog->get();
			$finalEmailLogData = [];
			foreach ($emailLogData as $emailLog) {
				$tempData = $emailLog;
				$successEmail = ($emailLog['success_email'] != '') ? explode(',', $emailLog['success_email']) : [];
				$failureEmail = ($emailLog['failure_email'] != '') ? explode(',', $emailLog['failure_email']) : [];
				$skippedEmail = ($emailLog['skipped_email'] != '') ? explode(',', $emailLog['skipped_email']) : [];
				$tempData['success_email_count'] = count($successEmail);
				$tempData['failure_email_count'] = count($failureEmail);
				$tempData['skipped_email_count'] = count($skippedEmail);
				$tempData['customer_email'] = $successEmail[0];
				unset($tempData['success_email'], $tempData['failure_email'], $tempData['skipped_email']);
				array_push($finalEmailLogData, $tempData);
			}
			$jsonResponse = [
				'status' => 1,
				'records' => count($finalEmailLogData),
				'total_records' => $getTotalPerFilters,
				'data' => $finalEmailLogData,
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * POST: Clear email log
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   02 Dec 2020
	 * @return json response
	 */
	public function clearDataForEmailLog($request, $response)
	{
		$getStoreDetails = get_store_details($request);
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Clear email log', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$emailLogId = $allPostPutVars['log_id'];
		if ($emailLogId != '' && $emailLogId > 0) {
			$emailLogInit = new EmailLog();
			$checkEmailLog = $emailLogInit->where([
				'store_id' => $getStoreDetails['store_id'],
				'xe_id' => $emailLogId,
			]);
			if ($checkEmailLog->count() > 0) {
				//Delete Record
				$emailLogInit->where('xe_id', $emailLogId)->delete();
				$jsonResponse = [
					'status' => 1,
					'message' => message('Clear email log', 'done'),
				];
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * GET: Clear email log
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashrib@riaxe.com
	 * @date   02 Dec 2020
	 * @return json response
	 */
	public function createCsvForEmailLog($request, $response, $args)
	{
		$getStoreDetails = get_store_details($request);
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('csv file', 'error'),
		];
		$type = $request->getQueryParam('type');
		if (!empty($args['id'])) {
			$emailLogId = $args['id'];
			$emailLogInit = new EmailLog();
			$checkEmailLog = $emailLogInit->where([
				'store_id' => $getStoreDetails['store_id'],
				'xe_id' => $emailLogId,
			]);
			if ($checkEmailLog->count() > 0) {
				//create csv file
				$getEmailLogData = $checkEmailLog->get();
				$getEmailLogData = json_clean_decode($getEmailLogData, true);
				if ($type == 'success') {
					$emailIdsArr = ($getEmailLogData[0]['success_email'] != '') ? explode(',', $getEmailLogData[0]['success_email']) : [];
					$filename = "success_email.csv";
				} elseif ($type == 'failure') {
					$emailIdsArr = ($getEmailLogData[0]['failure_email'] != '') ? explode(',', $getEmailLogData[0]['failure_email']) : [];
					$filename = "failure_email.csv";
				} elseif ($type == 'skipped') {
					$emailIdsArr = ($getEmailLogData[0]['skipped_email'] != '') ? explode(',', $getEmailLogData[0]['skipped_email']) : [];
					$filename = "skipped_email.csv";
				} elseif ($type == 'total') {
					$successEmailIdsArr = ($getEmailLogData[0]['success_email'] != '') ? explode(',', $getEmailLogData[0]['success_email']) : [];
					$failureEmailIdsArr = ($getEmailLogData[0]['failure_email'] != '') ? explode(',', $getEmailLogData[0]['failure_email']) : [];
					$skippedEmailIdsArr = ($getEmailLogData[0]['skipped_email'] != '') ? explode(',', $getEmailLogData[0]['skipped_email']) : [];
					$emailIdsArr = array_merge($successEmailIdsArr, $failureEmailIdsArr, $skippedEmailIdsArr);
					$filename = "total_email.csv";
				} else {
					$filename = "";
				}
				$fp = fopen('php://output', 'w');
				header('Content-type: application/csv');
				header('Content-Disposition: attachment; filename=' . $filename);
				$header[] = 'customer_email';
				fputcsv($fp, $header);
				foreach ($emailIdsArr as $key => $email) {
					$temp[$key]['customer_email'] = $email;
					fputcsv($fp, $temp[$key]);
				}
				$jsonResponse = [
					'status' => 1,
					'message' => message('Clear email log', 'done'),
				];
			}
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Read setting.json data
	 *
	 * @param $storeId  storeId
	 *
	 * @author debashrib@riaxe.com
	 * @date   21 Dec 2020
	 * @return JSON
	 */
	public function readSettingJsonFile($storeId)
	{
		$settingJsonContent = [];
		$settingLocation = path('abs', 'setting') . 'stores/' . $storeId;
		$jsonFilePath = $settingLocation . '/settings.json';
		if (file_exists($jsonFilePath)) {
			$settingJson = read_file($jsonFilePath);
			$settingJsonContent = json_clean_decode($settingJson, true);
		}
		return $settingJsonContent;
	}
	/**
	 * POST: Update active store
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author soumyas@riaxe.com
	 * @date   14 October 2020
	 * @return json
	 */
	public function storeActive($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Update Active Store Id', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$storeId = $allPostPutVars['store_id'] ? $allPostPutVars['store_id'] : 1;
		DB::table('stores')->where('xe_id', '>', 0)->update(['status' => 0]);
		$activeStoreInfo = DB::table('stores')->where('xe_id', '=', $storeId)->update(['status' => 1]);
		if ($activeStoreInfo > 0) {
			$jsonResponse = [
				'status' => 1,
				'message' => 'Updated successfully',
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}
	/**
	 * GET: PurchaseOrderStatusType
	 *
	 * @param $statusId
	 * @param $storeId
	 * @param $moduleId
	 *
	 * @author soumyas@riaxe.com
	 * @date   19 February 2021
	 * @return Array
	 */
	public function getPurchaseOrderStatusType($statusId, $storeId, $moduleId)
	{
		$statusDataToArray = [];
		$statusInit = new PurchaseOrderStatus();
		$statusArr = $statusInit
			->select('xe_id as id', 'type')
			->where(
				[
					'module_id' => $moduleId,
					'store_id' => $storeId,
					'xe_id' => $statusId,
				]
			)->orderBy('sort_order', 'ASC');
		if ($statusArr->count() > 0) {
			$statusData = $statusArr->get();
			$statusDataToArray = $statusData->toArray();
		}
		return $statusDataToArray[0];
	}
	/**
	 * GET: PurchaseOrderSlug
	 *
	 * @param $slug
	 * @param $storeId
	 * @param $moduleId
	 *
	 * @author soumyas@riaxe.com
	 * @date   19 February 2021
	 * @return Array
	 */
	public function getPurchaseOrderStatusIdBySlug($slug, $storeId, $moduleId)
	{
		$slugDataToArray = [];
		$statusInit = new PurchaseOrderStatus();
		$statusArr = $statusInit
			->select('xe_id as id', 'type')
			->where(
				[
					'module_id' => $moduleId,
					'store_id' => $storeId,
					'type' => $slug,
				]
			)->orderBy('sort_order', 'ASC');
		if ($statusArr->count() > 0) {

			$statusData = $statusArr->get();
			$slugDataToArray = $statusData->toArray();
		}
		return $slugDataToArray[0];
	}

	/**
	 * Get old job_card from setting table
	 *
	 * @param $storeId Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   27 Feb 2021
	 * @return array
	 */
	private function getOldJobId($storeId)
	{
		//Get old job_card from setting
		$settingInit = new ProductionHubSetting();
		$jobIdRes = $settingInit->select('setting_key', 'setting_value')
			->where(
				[
					'store_id' => $storeId,
					'module_id' => 4,
					'setting_key' => 'job_card',
				]
			);
		if ($jobIdRes->count()) {
			$jobArr = $jobIdRes->get()->toArray();
			$resResult = [];
			foreach ($jobArr as $jobData) {
				if ($jobData['setting_key'] == 'job_card') {
					$newArr['job_card'] = $jobData['setting_value'];
				}
				if ($newArr['job_card'] != '') {
					array_push($resResult, $newArr);
				}
			}
			$resResult = $resResult[0];
		}
		return $resResult;
	}

	/**
	 * Get old job_card from setting table
	 *
	 * @param $storeId Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   27 Feb 2021
	 * @return array
	 */
	private function getOldPOId($storeId)
	{
		//Get old purchase_order_id from setting
		$settingInit = new ProductionHubSetting();
		$poIdRes = $settingInit->select('setting_key', 'setting_value')
			->where(
				[
					'store_id' => $storeId,
					'module_id' => 3,
					'setting_key' => 'purchase_order_id',
				]
			);
		if ($poIdRes->count()) {
			$poArr = $poIdRes->get()->toArray();
			$resResult = [];
			foreach ($poArr as $poData) {
				if ($poData['setting_key'] == 'purchase_order_id') {
					$newArr['purchase_order_id'] = $poData['setting_value'];
				}
				if ($newArr['purchase_order_id'] != '') {
					array_push($resResult, $newArr);
				}
			}
			$resResult = $resResult[0];
		}
		return $resResult;
	}

	/**
	 * Change flag value of production setting
	 *
	 * @param $storeId Store Id
	 *
	 * @author debashrib@riaxe.com
	 * @date   27 Feb 2021
	 * @return array
	 */
	public function changeSettingFlagValue($storeId, $moduleId, $settingKey)
	{
		$resResult = false;
		$settingInit = new ProductionHubSetting();
		$res = $settingInit->select('setting_key', 'setting_value')
			->where(
				[
					'store_id' => $storeId,
					'module_id' => $moduleId,
					'setting_key' => $settingKey,
				]
			);
		if ($res->count()) {
			$settingInit->where(
				[
					'store_id' => $storeId,
					'module_id' => $moduleId,
					'setting_key' => $settingKey,
				]
			)->update(['flag' => '0']);
			$resResult = true;
		}
		return $resResult;
	}
	/**
	 * Get domain name
	 *
	 * @param $storeId Store Id
	 *
	 * @author soaumys@riaxe.com
	 * @date   02 march 2021
	 * @return array
	 */
	public function getStoreDomainName($storeId)
	{
		$storeDetailsArray = [];
		$storeDetails = DB::table('stores')->where('xe_id', '=', $storeId);
		if ($storeDetails->count() > 0) {
			$storeDetailsArray = $storeDetails->get()->toArray();
			$storeDetailsArray = (array) $storeDetailsArray[0];
		}
		return $storeDetailsArray;
	}
	/**
	 * Save Assets Images
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Arguments
	 *
	 * @author robert@imprintnext.com
	 * @date   09 Nov 2020
	 * @return json
	 */
	public function saveAssetImage($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$allPostPutVars = $request->getParsedBody();
		$getStoreDetails = get_store_details($request);
		$isS3Enabled = $this->checkS3Settings($getStoreDetails['store_id']);
		$generateThumb = [];
		$responseType = empty($args['return_type']) ? 'json' : 'array';
		// Thumb generation status
		if (!empty($allPostPutVars['thumb'])) {
			$generateThumb[] = $allPostPutVars['thumb'];
		}
		$getCapturedImages = [];
		$jsonResponse = [
			'status' => 0,
			'message' => 'Image save failed',
		];
		// Get conditional resourse type
		$resourceType = '';
		if (!empty($allPostPutVars['type'])) {
			$resourceType = $allPostPutVars['type'];
			$resourceDirW = ASSETS_PATH_W . $resourceType;
			if (!is_dir($resourceDirW)) {
				mkdir($resourceDirW, 0755);
			}
			$resourceDirR = ASSETS_PATH_R . $resourceType;
			$getImageNames = do_upload(
				'images',
				$resourceDirW,
				$generateThumb,
				'array'
			);
			if ($isS3Enabled) {
				$fileToUpload = $resourceDirW . '/' . $getImageNames[0];
				$this->uploadFileToS3("stickers", $fileToUpload, $getStoreDetails['store_id']);
			}
			if (!empty($getImageNames)) {
				foreach ($getImageNames as $fileKey => $fileName) {
					$file = $resourceDirR . '/' . $fileName;
					if ($isS3Enabled) {
						$s3URL =  $this->getS3URL($file, $getStoreDetails['store_id']);
						$getCapturedImages['images'][$fileKey] = [
							'url' => $s3URL,
						];
					} else {
						$getCapturedImages['images'][$fileKey] = [
							'url' => $file,
						];
					}
					// Send file_name according to the format requested
					if ($responseType == 'array') {
						$getCapturedImages['images'][$fileKey] += [
							'file_name' => $fileName,
						];
					}
					// Conditional thumnail response will go
					if (!empty($allPostPutVars['thumb'])) {
						$getCapturedImages['images'][$fileKey] += [
							'thumbnail' => $resourceDirR . '/' . 'thumb_' . $fileName,
						];
					}
				}
				$jsonResponse = [
					'status' => 1,
					'data' => $getCapturedImages,
				];
			}
		}

		if ($responseType == 'json') {
			return response(
				$response,
				['data' => $jsonResponse, 'status' => $serverStatusCode]
			);
		}
		return $getCapturedImages;
	}
	/**
	 * Reset a Category & Subcategory as Default
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $args     Slim's Argument parameters
	 *
	 * @author soumyas@riaxe.com
	 * @date   27 May 2021
	 * @return json
	 */
	public function resetDefault($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Category', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$defaultIds = $allPostPutVars['default'];
		$assetTypeArr = $this->assetsTypeId($args['slug']);
		if (!empty($args['slug']) && !empty($assetTypeArr['status']) && !empty($defaultIds)) {
			$getDefaultIds = json_clean_decode($defaultIds, true);
			foreach ($getDefaultIds as $defaultId) {
				$getCategoryInit = new Category();
				$categories = $getCategoryInit->where('xe_id', $defaultId);
				if ($categories->count() > 0) {
					$updateData = ['is_default' => 0];
					$categoryUpdateInit = new Category();
					$categoryUpdateInit->where('xe_id', '=', $defaultId)->where('asset_type_id', '=', $assetTypeArr['asset_type_id'])->update($updateData);
				}
			}
			$jsonResponse = [
				'status' => 1,
				'message' => message('Category', 'done'),
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Check S3 settings
	 *
	 * @param $storeId Store Id
	 *
	 * @author debashisd@riaxe.com
	 * @date   13 April 2021
	 * @return Boolean
	 */
	public function checkS3Settings($storeId, $returnS3URL = false)
	{
		$settingLocation = path('abs', 'setting') . 'stores/' . $storeId . '/S3Data.xml';
		$saveFileInS3 = false;
		if (file_exists($settingLocation)) {
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			$flag = $dom->getElementsByTagName('is_enabled')->item(0)->nodeValue;
			if ($flag == 'true') {
				$saveFileInS3 = true;
			}
			if ($returnS3URL) {
				$baseS3URL = $dom->getElementsByTagName('base_url')->item(0)->nodeValue;
				return array("is_enabled" => $saveFileInS3, "base_s3_URL" => $baseS3URL);
			}
		}
		return $saveFileInS3;
	}

	/**
	 * upload single object or file to S3
	 *
	 * @param $storeId Store Id Integer
	 * @param $module module name string
	 * @param $fileToUpload fuleDIR string
	 *
	 * @author debashisd@riaxe.com
	 * @date   13 April 2021
	 * @return Array
	 */
	public function uploadFileToS3($module = "", $fileToUpload = null, $storeId = 1)
	{
		require_once getcwd() . '/app/Dependencies/aws/aws-autoloader.php';
		$settingLocation = path('abs', 'setting') . 'stores/' . $storeId . '/S3Data.xml';
		$keyName = substr($fileToUpload, strrpos($fileToUpload, 'assets'));
		$response['error'] = 1;
		if (file_exists($settingLocation)) {
			// get S3 credentials from saved setting xml
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			$awsKey = $dom->getElementsByTagName('aws_key')->item(0)->nodeValue;
			$S3Secret = $dom->getElementsByTagName('s3_secret')->item(0)->nodeValue;
			$S3region = $dom->getElementsByTagName('region')->item(0)->nodeValue;
			$s3Bucket = $dom->getElementsByTagName('bucket')->item(0)->nodeValue;
			// create s3 client
			try {
				$s3Client = new \Aws\S3\S3Client([
					'region' => $S3region,
					'version' => 'latest',
					'credentials' => array(
						'key' => $awsKey,
						'secret' => $S3Secret
					),
				]);
				if (strpos($keyName, '.svg') !== false) {
					$result = $s3Client->putObject(array(
						'Bucket'     => $s3Bucket,
						'Key'        => $keyName,
						'SourceFile' => $fileToUpload,
						'ACL' => 'public-read',
						'ContentType' => 'image/svg+xml',
					));
				} else {
					$result = $s3Client->putObject(array(
						'Bucket'     => $s3Bucket,
						'Key'        => $keyName,
						'SourceFile' => $fileToUpload,
						'ACL' => 'public-read',
					));
				}
				unlink($fileToUpload);
				//call getS3URL again to check if cloudfront is enabled
				$thisFiles3URL = $this->getS3URL(substr($result['ObjectURL'], strpos($result['ObjectURL'], "/assets/"), strlen($result['ObjectURL'])), $storeId);
				$response = array('error' => 0, 'S3URL' => $thisFiles3URL);
			} catch (\Exception $e) {
				$response['error'] = 1;
			}
		}
		return $response;
	}

	/**
	 * upload whole directory to S3
	 *
	 * @param $storeId Store Id Integer
	 * @param $module module name string
	 * @param $fileToUpload fuleDIR string
	 *
	 * @author debashisd@riaxe.com
	 * @date   13 April 2021
	 * @return Array
	 */
	public function uploadDIRToS3Recurse($module = "", $directory = null, $storeId = 1)
	{
		require_once getcwd() . '/app/Dependencies/aws/aws-autoloader.php';
		$settingLocation = path('abs', 'setting') . 'stores/' . $storeId . '/S3Data.xml';
		$keyName = (!empty($module) ? $module : substr($directory, strpos($directory, '/assets')));
		$response['error'] = 1;
		if (file_exists($settingLocation)) {
			// get S3 credentials from saved setting xml
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			$awsKey = $dom->getElementsByTagName('aws_key')->item(0)->nodeValue;
			$S3Secret = $dom->getElementsByTagName('s3_secret')->item(0)->nodeValue;
			$S3region = $dom->getElementsByTagName('region')->item(0)->nodeValue;
			$s3Bucket = $dom->getElementsByTagName('bucket')->item(0)->nodeValue;
			// create s3 client
			try {
				$s3Client = new \Aws\S3\S3Client([
					'region' => $S3region,
					'version' => 'latest',
					'credentials' => array(
						'key' => $awsKey,
						'secret' => $S3Secret
					),
				]);
				// Where the files will be transferred to
				$dest = 's3://' . $s3Bucket . $keyName;
				$manager = new \Aws\S3\Transfer($s3Client, $directory, $dest);
				// Perform the transfer synchronously
				$manager->transfer();
				$this->deleteRecurseDIR($directory);
				$response = array('error' => 0);
			} catch (\Exception $e) {
				$response['error'] = 1;
			}
		}
		return $response;
	}

	/**
	 * Delete S3 files
	 *
	 * @param $storeId Store Id Integer
	 * @param $file fuleDIR string
	 *
	 * @author debashisd@riaxe.com
	 * @date   15 June 2021
	 * @return String
	 */
	public function deleteRecurseDIR($dir)
	{
		if (is_dir($dir)) {
			$files = glob($dir . '*', GLOB_MARK); //GLOB_MARK adds a slash to directories returned

			foreach ($files as $file) {
				$this->deleteRecurseDIR($file);
			}

			rmdir($dir);
		} elseif (is_file($dir)) {
			unlink($dir);
		} else {
			// Nothing to do
		}
	}

	/**
	 * download whole directory to S3
	 *
	 * @param $storeId Store Id Integer
	 * @param $module module name string
	 * @param $fileToUpload fuleDIR string
	 *
	 * @author debashisd@riaxe.com
	 * @date   13 April 2021
	 * @return Array
	 */
	public function downloadS3Content($keyName = "", $directory = null, $storeId = 1)
	{
		require_once getcwd() . '/app/Dependencies/aws/aws-autoloader.php';
		$settingLocation = path('abs', 'setting') . 'stores/' . $storeId . '/S3Data.xml';
		$response['error'] = 1;
		if (file_exists($settingLocation)) {
			// get S3 credentials from saved setting xml
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			$awsKey = $dom->getElementsByTagName('aws_key')->item(0)->nodeValue;
			$S3Secret = $dom->getElementsByTagName('s3_secret')->item(0)->nodeValue;
			$S3region = $dom->getElementsByTagName('region')->item(0)->nodeValue;
			$s3Bucket = $dom->getElementsByTagName('bucket')->item(0)->nodeValue;
			// create s3 client
			try {
				$s3Client = new \Aws\S3\S3Client([
					'region' => $S3region,
					'version' => 'latest',
					'credentials' => array(
						'key' => $awsKey,
						'secret' => $S3Secret
					),
				]);
				// Where the files will be transferred to
				$source = 's3://' . $s3Bucket . $keyName;
				$manager = new \Aws\S3\Transfer($s3Client, $source, $directory);
				// Perform the transfer synchronously
				$manager->transfer();
				$response = array('error' => 0);
			} catch (\Exception $e) {
				$response['error'] = 1;
			}
		}
		return $response;
	}

	/**
	 * Get public URL of S3 files
	 *
	 * @param $storeId Store Id Integer
	 * @param $file fuleDIR string
	 *
	 * @author debashisd@riaxe.com
	 * @date   13 April 2021
	 * @return String
	 */
	public function getS3URL($file, $storeId)
	{
		// get the key name for the s3 bucket
		$keyName = substr($file, strpos($file, 'assets'));
		// default send the file if s3 config is not done
		$contentURL = $file;
		if (empty($this->s3Settings[$storeId])) {
			$settingLocation = path('abs', 'setting') . 'stores/' . $storeId . '/S3Data.xml';
			if (!file_exists($settingLocation)) {
				return $contentURL;
			}
			// get S3 credentials from saved setting xml
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			// do not proceed if xml doesn't have s3 data
			if ($dom->getElementsByTagName('s3')->length == 0) {
				return $contentURL;
			}
			// get the flag for the cloudfront
			$this->s3Settings[$storeId] = [
				'is_enabled' => $dom->getElementsByTagName('is_enabled')->item(0)->nodeValue == 'true',
				'base_url' => $dom->getElementsByTagName('base_url')->item(0)->nodeValue,
				'enable_cloudfront' => $dom->getElementsByTagName('enable_cloudfront')->item(0)->nodeValue == 'true',
				'cloudfront_url' => $dom->getElementsByTagName('cloudfront_url')->item(0)->nodeValue
			];
		}

		if ($this->s3Settings[$storeId]['enable_cloudfront']) {
			// get the content via cloudfront
			$contentURL = $this->s3Settings[$storeId]['cloudfront_url'] . $keyName;
		} else {
			// get the content from the S3 if base url found
			if (!empty($this->s3Settings[$storeId]['base_url'])) {
				$contentURL = $this->s3Settings[$storeId]['base_url'] . $keyName;
			}
		}

		return $contentURL;
	}

	/*
    delete files from s3
	*/
	public function deleteS3File($file, $storeId)
	{
		require_once getcwd() . '/app/Dependencies/aws/aws-autoloader.php';
		$deleteStatus = 0;
		$keyName = substr($file, strpos($file, 'assets'));
		$settingLocation = path('abs', 'setting') . 'stores/' . $storeId . '/S3Data.xml';
		if (file_exists($settingLocation)) {
			// get S3 credentials from saved setting xml
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			$awsKey = $dom->getElementsByTagName('aws_key')->item(0)->nodeValue;
			$S3Secret = $dom->getElementsByTagName('s3_secret')->item(0)->nodeValue;
			$S3region = $dom->getElementsByTagName('region')->item(0)->nodeValue;
			$s3Bucket = $dom->getElementsByTagName('bucket')->item(0)->nodeValue;
			// create s3 client
			try {
				$s3Client = new \Aws\S3\S3Client([
					'region' => $S3region,
					'version' => 'latest',
					'credentials' => array(
						'key' => $awsKey,
						'secret' => $S3Secret
					),
				]);
				if ($s3Client->doesObjectExist($s3Bucket, $keyName)) {
					$s3Client->deleteObject([
						'Bucket' => $s3Bucket,
						'Key' => $keyName,
					]);
					$deleteStatus = 1;
				} else {
					$deleteStatus = 1;
				}
			} catch (\Exception $e) {
				$response['error'] = 1;
			}
		}
		return $deleteStatus;
	}

	/**
	 * GET: Mac Id
	 *
	 * @author debashisd@riaxe.com
	 * @date   09 Jun 2020
	 * @return Get Mac Id
	 */
	public function getMacId()
	{
		$mac = "";
		if (PHP_OS == "Linux") {
			// For Linux system
			ob_start();
			shell_exec('ifconfig -a');
			$mycom = ob_get_contents(); // Capture the output into a variable
			ob_clean(); // Clean (erase) the output buffer
			$findme = "Physical";
			//Find the position of Physical text 
			$pmac = strpos($mycom, $findme);
			$mac = substr($mycom, ($pmac + 37), 18);
		} else {
			$mac = exec('getmac');
			$mac = strtok($mac, ' ');
		}
		return trim($mac);
	}


	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Server Space
	 */

	public function getserverspace($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('No image found', 'error'),
		];
		$this->diskPath = '.';
		$freeSpace = $this->freeSpace();
		$totalSpace = $this->totalSpace();
		$jsonResponse = [
			'status' => 1,
			'freeSpace' => $freeSpace,
			'totalSpace' => $totalSpace,
		];
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Server Free Space
	 */
	public function freeSpace($rawOutput = false)
	{
		$diskFreeSpace = @disk_free_space($this->diskPath);
		if ($diskFreeSpace === FALSE) {
			throw new Exception('freeSpace(): Invalid disk path.');
		}
		return $diskFreeSpace;
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Server Total Space
	 */
	public function totalSpace($rawOutput = false)
	{
		$diskTotalSpace = @disk_total_space($this->diskPath);
		if ($diskTotalSpace === FALSE) {
			throw new Exception('totalSpace(): Invalid disk path.');
		}
		return $diskTotalSpace;
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Delete Server File Space
	 */
	public function deleteFile($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$this->deleteOrderFile();
		$this->deleteCartFile();
		$this->deleteBrowserFile();
		$this->deleteUserImageFile();
		$jsonResponse = [
			'status' => 1,
			'message' => 'Removed',
		];

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Delete Order File
	 */
	private function deleteOrderFile()
	{
		$folder = ASSETS_PATH_W . "orders";
		$fromDate =  date('Y-m-d', strtotime("-30 days"));
		return $this->setPathtoDelete($folder, $fromDate);
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Delete Cart File
	 */
	private function deleteCartFile()
	{
		$folder = ASSETS_PATH_W . "design_previews/carts";
		$fromDate =  date('Y-m-d', strtotime("-60 days"));
		return $this->setPathtoDelete($folder, $fromDate);
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Delete Browser Image File
	 */
	private function deleteBrowserFile()
	{
		create_log(
			'Server_Disk_Space',
			'error',
			[
				'message' => "path: " . ASSETS_PATH_W . 'browser_images/' . " Till Date:" . date("Y-m-d"),
				'extra' => [
					'module' => 'Delete Old Files where customer id = 0',
				],
			]
		);

		$folder = ASSETS_PATH_W . "browser_images";
		$fromDate =  date('Y-m-d', strtotime("-30 days"));
		return $this->setPathtoDelete($folder, $fromDate);
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Delete User Image File
	 */
	private function deleteUserImageFile()
	{
		$folder = ASSETS_PATH_W . "user";
		$fromDate =  date('Y-m-d', strtotime("-30 days"));
		$this->setPathtoDelete($folder, $fromDate);
		$this->setPathtoDelete($folder . "/uploads", $fromDate);

		create_log(
			'Server_Disk_Space',
			'error',
			[
				'message' => "path: " . ASSETS_PATH_W . 'user/' . " Till Date:" . date("y-m-d"),
				'extra' => [
					'module' => 'Delete Old Files where customer id = 0',
				],
			]
		);
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Delete File From Path
	 */
	private function deleteFileFromPath($path)
	{
		$path = explode('assets/', $path);
		$filePath = ASSETS_PATH_W . $path[1];
		if (file_exists($filePath)) {
			unlink($filePath);
		}
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Path to delete using date
	 */
	private function setPathtoDelete($folder, $fromDate)
	{
		$count = 0;
		$saved = array('index.html', ".", "..");
		$order  = scandir($folder);
		foreach ($order as $file) {
			$fileDate =  date("Y-m-d", filemtime($folder . "/" . $file));
			if (!in_array($file, $saved) && ($fromDate >= $fileDate)) {
				is_file($folder . "/" . $file) ?   unlink($folder . "/" . $file) : $this->removeDirectory($folder . "/" . $file);
				$count++;
			}
		}

		create_log(
			'Server_Disk_Space',
			'error',
			[
				'message' => "path: " . $folder . " Till Date:" . $fromDate,
				'extra' => [
					'module' => 'Delete Old Files',
				],
			]
		);

		return $count;
	}
	/**
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 * @param $storeId   Store Id    
	 *
	 * @author steve@imprintnext.com
	 * @date   1 Dec 2021
	 * @return Remove Directory along with its file
	 */
	private function removeDirectory($path)
	{
		$files = glob($path . '/*');
		foreach ($files as $file) {
			is_dir($file) ? $this->removeDirectory($file) : unlink($file);
		}
		rmdir($path);
		return;
	}
	/**
	 * Save: Barcode details
	 *
	 * @param $moduleId 
	 * @param $storeId 
	 * @param $moduleName 
	 * @param $moduleSlug 
	 * @param $returnArray 
	 *
	 * @author soumyas@riaxe.com
	 * @date   04 April 2022
	 * @return Json / Array response
	 */
	public function barcodeGenerate($moduleId, $storeId, $moduleName, $moduleSlug, $isArray)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('BarCode', 'error'),
		];
		$barCodePath =  ASSETS_PATH_W . 'bar_codes';
		if (!is_dir($barCodePath)) {
			mkdir($barCodePath, 0777, true);
		}
		$randomNumber =  trim(getRandom());
		$barCodesInit = new BarCodes();
		$getBarCodeData = $barCodesInit->where(['barcode_number' => $randomNumber, 'store_id' => $storeId, 'module_id' => $moduleId]);
		if ($getBarCodeData->count() > 0) {
			$randomNumber =  trim(getRandom());
		}
		$saveData = ['name' => $moduleName, 'slug' => $moduleSlug, 'module_id' => $moduleId, 'barcode_number' => $randomNumber, 'barcode_image' => $randomNumber . '.png', 'store_id' => $storeId, 'is_active' => 1];
		$barCodesSaveInit = new BarCodes($saveData);
		$barCodesSaveInit->save();
		$lastInsertId = $barCodesSaveInit->xe_id;
		if ($lastInsertId > 0) {
			$barCodePath =  ASSETS_PATH_W . 'bar_codes/' . $randomNumber . '.png';
			$barcode = generate_barcode($randomNumber);
			file_put_contents($barCodePath, $barcode);
			$jsonResponse = [
				'status' => 1,
				'message' => "Record saved into application",
			];
		}
		if ($isArray == 1) {
			return $lastInsertId;
		} else {
			return response(
				$response,
				['data' => $jsonResponse, 'status' => $serverStatusCode]
			);
		}
	}
	/**
	 * Update: Barcode name
	 *
	 * @param $moduleId 
	 * @param $slug 
	 * @param $newName 
	 * @param $storeId 
	 * @author soumyas@riaxe.com
	 * @date   04 April 2022
	 * @return boolean
	 */
	public function updateBarCodeStatusName($moduleId, $statusId, $newName, $storeId)
	{
		$updateStatus = false;
		$productionStatusInit =  new ProductionStatus();
		$getProductionStatus =  $productionStatusInit->where(['xe_id' => $statusId, 'module_id' => $moduleId, 'store_id' => $storeId]);
		if ($getProductionStatus->count() > 0) {
			$getProductionStatusData =  $getProductionStatus->first()->toArray();
			$slug = $getProductionStatusData['slug'];
			$barCodesSaveInit = new BarCodes();
			$updateData = ['name' => $newName];
			$status =  $barCodesSaveInit->where('slug', '=', $slug)->where('store_id', '=', $storeId)->where('module_id', '=', $moduleId)->update($updateData);
			if ($status) {
				$updateStatus = true;
			}
		}
		return $updateStatus;
	}
	/**
	 * Enable or Disable particular print profile by ID
	 *
	 * @param $printProfileId 
	 * @param $assetsId 
	 * @param $categoryId 
	 *
	 * @author soumyas@riaxe.com
	 * @date   3 October 2022
	 * @return Boolean
	 */
	private function checkCategorySelected($printProfileId, $assetTypeId, $categoryId)
	{
		if (!empty($assetTypeId) && !empty($categoryId)) {
			$profileCatRelObj = new \App\Modules\PrintProfiles\Models\PrintProfileAssetsCategoryRel();
			$profileCatRelDetails = $profileCatRelObj->where(['asset_type_id' => $assetTypeId, 'category_id' => $categoryId, 'print_profile_id' => $printProfileId])->first();
			if ($profileCatRelDetails !== null && $profileCatRelDetails->count() > 0) {
				return true;
			}
		}
		return false;
	}
	/**
	 * Get admin default language name
	 *
	 * @param $storeId 
	 * @param $type 
	 *
	 * @author soumyas@riaxe.com
	 * @date   2 Feb 2023
	 * @return Array
	 */
	public function getDefaultLanguageFont($storeId, $type = "admin", $lang = '')
	{
		$fontArray = [];
		if (empty($lang)) {
			$where = ['type' => $type, 'is_default' => 1, 'store_id' => $storeId];
		} else {
			$where = ['type' => $type, 'name' => $lang, 'store_id' => $storeId];
		}
		$languageInit = new Language();
		$getLanguage = $languageInit->where($where);
		if ($getLanguage->count() > 0) {
			$getLanguageData = $getLanguage->first()->toArray();
			if (!empty($getLanguageData)) {
				if (strtolower($getLanguageData['name']) == "chinese") {
					$fontArray['font_family'] = "Firefly Sung";
					$fontArray['font_all'] = "Firefly Sung, DejaVu Sans, sans-serif";
					$fontArray['font_style'] = "normal";
					$fontArray['font_weight'] = "400";
					$fontArray['font_url'] = path("read", "common") . 'fireflysung.ttf';
					$fontArray['true_type'] = "truetype";
				} elseif (strtolower($getLanguageData['name']) == "japanese") {
					$fontArray['font_family'] = "Nasu";
					$fontArray['font_all'] = "Nasu, sans-serif";
					$fontArray['font_style'] = "normal";
					$fontArray['font_weight'] = "400";
					$fontArray['font_url'] = path("read", "common") . 'Nasu-Regular.ttf';
					$fontArray['true_type'] = "truetype";
				} elseif (strtolower($getLanguageData['name']) == "hebrew") {
					$fontArray['font_family'] = "chinese";
					$fontArray['font_all'] = "DejaVu Sans, sans-serif";
					$fontArray['font_style'] = "normal";
					$fontArray['font_weight'] = "400";
					$fontArray['font_url'] = path("read", "common") . 'wts11.ttf';
					$fontArray['true_type'] = "truetype";
					$fontArray['style'] = "rtl";
				} else {
					$fontArray['font_family'] = "Aozora Mincho";
					$fontArray['font_all'] = "Aozora Mincho, Firefly Sung, DejaVu Sans, sans-serif";
					$fontArray['font_style'] = "normal";
					$fontArray['font_weight'] = "400";
					$fontArray['font_url'] = path("read", "common") . 'AozoraMinchoMedium.ttf';
					$fontArray['true_type'] = "truetype";
				}
			}
		}
		return $fontArray;
	}

	/**
	 * POST : Test mail
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author mike@imprintnext.com
	 * @date   08 Feb 2023
	 * @return json response of success and failure message.
	 */
	public function smtpMailTest($request, $response)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'message' => message('Email Sent', 'error'),
		];
		$allPostPutVars = $request->getParsedBody();
		$emailData = $allPostPutVars['maildetails'];
		$fromMailData = $allPostPutVars['email_address_details'];
		$isMailSent = $allPostPutVars['is_varify'];
		$smtpData = json_decode($emailData, true);
		$fromData = json_decode($fromMailData, true);
		$subject = 'Test Mail -' . $_SERVER['SERVER_NAME'];
		$getStoreDetails = get_store_details($request);
		$storeId = $getStoreDetails['store_id'] ? $getStoreDetails['store_id'] : 1;
		if (empty($smtpData['smtp_pass'])) {
			$settingKey = 'smtp_details';
			$type = 1;
			$smtpData['smtp_pass'] = $this->getSmtpPassword($settingKey, $type, $storeId);
		}
		$message = '<!DOCTYPE html>
			<html>
			<head>
			<title>Email Test</title>
			</head>
			<body style="padding: 0; margin: 0;">

			<table width="100%" border="0" cellspacing="0" cellpadding="0">
			    <tbody>
			        <tr>
			            <td align="center" valign="top" style="background: #ebeef4; padding: 60px 30px;">
			                <table width="600px" border="0" cellspacing="0" cellpadding="0">
			                    <tbody>
			                        <tr>
			                            <td align="left" valign="top" style="background: #fff; padding:25px 30px; border-radius: 6px; font-family: Arial, Helvetica, sans-serif;">
			                                <p style="font-size:20px">Hi,</p>
			                                <p style="font-size:18px">This is a test mail generated from ' . $_SERVER['SERVER_NAME'] . '</p>
			                                <p style="font-size:18px; color: #666;">Please do not reply to this email.</p>
			                                <p style="font-size:20px; color: blue;"><span style="font-size:18px; color: #666;">Thank you</span><br>' . $_SERVER['SERVER_NAME'] . '</p>
			                            </td>
			                        </tr>
			                    </tbody>
			                </table>
			            </td>
			        </tr>
			    </tbody>
			</table>

			</body>
			</html>';
		if (!empty($smtpData)) {
			$replyToEmail = '';
			$attachments = [];
			$fromEmail = $smtpData['smtp_from'];
			$fromName = $fromData['from_email'];
			$customerEmail = $smtpData['to_email'];
			$mailContaint = [
				'from' => ['email' => $fromEmail, 'name' => $fromName],
				'recipients' => [
					'to' => [
						'email' => $customerEmail,
						'name' => '',
					],
					'reply_to' => [
						'email' => $replyToEmail,
						'name' => $replyToEmail,
					],
				],
				'attachments' => ($attachments != '') ? $attachments : [],
				'subject' => $subject,
				'body' => $message,
				'smptData' => $smtpData,
			];

			//Checked if varify or not
			if (empty($smtpData['smtp_pass'])) {
				$settingsInit = new \App\Modules\Settings\Models\Setting();
				$getSMTPData = $settingsInit->select('setting_value')->where('setting_key', 'smtp_details')
					->first();
				$mailData = json_decode($getSMTPData->setting_value, true);
				if (!empty($mailData['smtp_user']) && !empty($mailData['smtp_pass'])) {
					$mailData['smtp_pass'] = $this->decryptKey($mailData['smtp_pass']);
				} else {
					$mailData = $smtpData;
				}
			} else {
				$mailData = $smtpData;
			}
			if ((isset($mailData['smtp_varify']) && $mailData['smtp_varify'] == 1) && !$isMailSent) {
				if (($smtpData['smtp_user'] == $mailData['smtp_user']) && ($smtpData['smtp_pass'] == $mailData['smtp_pass']) && ($smtpData['smtp_host'] == $mailData['smtp_host']) && ($smtpData['smtp_from'] == $mailData['smtp_from']) && ($smtpData['smtp_name'] == $mailData['smtp_name']) && ($smtpData['smtp_port'] == $mailData['smtp_port']) && ($smtpData['smtp_secure'] == $mailData['smtp_secure']) && ($smtpData['smtp_auth'] == $mailData['smtp_auth']) && ($smtpData['smtp_debug'] == $mailData['smtp_debug']) && ($smtpData['smtp_type'] == $mailData['smtp_type'])) {
					$jsonResponse = [
						'status' => 1,
						'message' => 'SMTP authentication is verified.',
					];
				} else {
					$jsonResponse = $this->checkMailAndUpdataeVarifyStatus($smtpData, $mailContaint, $mailData);
				}
			} else {
				$jsonResponse = $this->checkMailAndUpdataeVarifyStatus($smtpData, $mailContaint, $mailData);
			}
		} else {
			$jsonResponse = [
				'status' => 0,
				'message' => 'Wrong data entry.',
			];
		}

		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * Internal function for mail fair and setting data update
	 *
	 * @param $smtpData
	 * @param $mailContaint
	 * @param $mailData
	 *
	 * @author mike@imprintnext.com
	 * @date   01 Aug 2023
	 * @return json response
	 */
	private function checkMailAndUpdataeVarifyStatus($smtpData, $mailContaint, $mailData)
	{
		$jsonResponse = [];
		if ($smtpData['smtp_host'] != '' && $smtpData['smtp_user'] != '' && $smtpData['smtp_pass'] != '') {
			$mailResponse = email($mailContaint);
		} else {
			$mailResponse['status'] = 0;
		}
		if (!empty($mailResponse['status']) && $mailResponse['status'] == 1) {
			$jsonResponse = [
				'status' => 1,
				'message' => 'SMTP authentication is verified.',
			];
			// Update Settings Data
			$settingsInit = new \App\Modules\Settings\Models\Setting();
			$updateData = [];
			$mailData['smtp_varify'] = 1;
			$mailData['smtp_pass'] = $this->encryptKey($mailData['smtp_pass']);
			$updateData['setting_value'] = json_encode($mailData);
			$settingsInit->where('setting_key', '=', 'smtp_details')->update($updateData);
			// End
		} else {
			$jsonResponse = [
				'status' => 0,
				'message' => 'SMTP authentication error, check the credentials.',
			];
		}
		return $jsonResponse;
	}

	/**
	 * GET : Quote setting for My-Account
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author soumyas@riaxe.com
	 * @date   29 June 2023
	 * @return json response of success and failure message.
	 */
	public function enableQuoteForMyAccount($request, $response, $args)
	{
		$serverStatusCode = OPERATION_OKAY;
		$jsonResponse = [
			'status' => 0,
			'data' => [],
			'message' => message('Enable Quote', 'error'),
		];
		$getStoreDetails = get_store_details($request);
		$storeId = $getStoreDetails['store_id'] ? $getStoreDetails['store_id'] : 1;
		$productionSettingInit = new ProductionHubSetting();
		$getProductionSetting = $productionSettingInit->where(['store_id' => $storeId, 'setting_key' => 'is_show_dashboard_quotes']);
		if ($getProductionSetting->count() > 0) {
			$getSettingData = $getProductionSetting->first()->toArray();
			$jsonResponse = [
				'status' => 1,
				'data' => ['is_show_quotes' => $getSettingData['setting_value']],
			];
		}
		return response(
			$response,
			['data' => $jsonResponse, 'status' => $serverStatusCode]
		);
	}

	/**
	 * create asset cache
	 *
	 * @param $request  
	 *
	 *
	 * @author pansy@imprintnext.com
	 * @date   9 Apr 2024
	 */

	public function createAssetCache($moduleName, $storeId, $printProfile, $assetData, $page)
	{
		$assetCacheContent = [];
		$printProfileId = (is_string($printProfile) && strlen($printProfile) > 1) ? json_decode($printProfile, true) : $printProfile;
		if (is_array($printProfileId)) {
			$printProfileId = $printProfileId[0];
		}
		$cacheJsonFile = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $printProfileId . "_" . $moduleName . '_cache.json';
		if (file_exists($cacheJsonFile) && $page == 2) {
			$assetCacheContent = json_decode(file_get_contents($cacheJsonFile), true);
			$assetCacheContent['data'] = array_merge($assetCacheContent['data'], $assetData);
			file_put_contents($cacheJsonFile, json_encode($assetCacheContent), true);
		} elseif ($page == 1) {
			$cacheDir = ASSETS_PATH_W . 'cache';
			if (!is_dir($cacheDir)) {
				mkdir($cacheDir, 0777, true);
			}
			$designAssetDir = $cacheDir . '/design_assets';
			if (!is_dir($designAssetDir)) {
				mkdir($designAssetDir, 0777, true);
			}
			file_put_contents($cacheJsonFile, json_encode($assetData));
		}
	}

	/**
	 * get asset cache   
	 *
	 * @param $request  
	 *
	 *
	 * @author pansy@imprintnext.com
	 * @date   9 Apr 2024
	 * @return json 
	 */

	public function getAssetCache($storeId, $printProfile, $page, $perpage, $moduleName, $is_cms = 0)
	{
		//get asset cache
		$assetResponse = [];
		$printProfileId = strlen($printProfile) > 1 ? json_decode($printProfile, true) : $printProfile;
		if (is_array($printProfileId)) {
			$printProfileId = $printProfileId[0];
		}
		if ($is_cms == 1) {
			$printProfileId = '';
		}
		$cacheJsonFile = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $printProfileId . "_" . $moduleName . '_cache.json';

		if (file_exists($cacheJsonFile)) {
			$assetCache = json_decode(file_get_contents($cacheJsonFile), true);
			$assetTotalRecords = $assetCache['total_records'];
			$assetCacheContent = $assetCache['data'];
			$offset = ($page - 1) * $perpage;
			if ($offset == 0) {
				$assetResponse = array_slice($assetCacheContent, $offset, $perpage);
			} elseif ($offset > 0 && count($assetCacheContent) >  $offset) {
				$assetResponse = array_slice($assetCacheContent, $offset, $perpage);
			}
			if (!empty($assetResponse)) {
				return ([
					'total_records' => $assetTotalRecords,
					'data' => $assetResponse
				]);
			} else {
				return $assetResponse;
			}
		}
	}

	/**
	 * update asset cache   
	 *
	 * @param $request  
	 *
	 *
	 * @author pansy@imprintnext.com
	 * @date   11 Apr 2024
	 * @return json 
	 */

	public function updateAssetCache($storeId, $assetId, $getParams, $moduleName)
	{

		$response = [];
		$categoryIds = [];
		//while asset update and save 
		if (isset($getParams['categories']) && !empty($getParams['categories'])) {
			$categoryIds = json_decode($getParams['categories'], true);
		} elseif ($_SERVER["REQUEST_METHOD"] == "DELETE" && !empty($assetId)) {
			$categoryIds = $getParams;
		}
		if (!empty($categoryIds)) {
			$ppAssetCatRelGtInit = new PrintProfileModels\PrintProfileAssetsCategoryRel();
			$printProfileIds = $ppAssetCatRelGtInit->whereIn('category_id', $categoryIds)->distinct()->pluck('print_profile_id');
			$availablepp = [];
			foreach ($printProfileIds as $printProfileId) {
				$cacheJsonFile = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $printProfileId . "_" . $moduleName . '_cache.json';
				if (file_exists($cacheJsonFile)) {
					unlink($cacheJsonFile);
					$availablepp[] = $printProfileId;
				}
			}
		} else {
			//while print method update and save
			$modulesArray = ['clipart', 'font', 'template', 'colorpalette'];
			$printProfileId = $printprofileArray = strlen($getParams['print_profile_id']) > 1 ? json_decode($getParams['print_profile_id'], true) : $getParams['print_profile_id'];
			foreach ($modulesArray as $eachModule) {
				$cacheDir = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $getParams['print_profile_id'] . "_" . $eachModule . '_cache.json';
				if (file_exists($cacheDir)) {
					unlink($cacheDir);
					$availablepp[] = $getParams['print_profile_id'];
				} else {
					$availablepp[] = $getParams['print_profile_id'];
				}

				// is_edit and is_cms key not available on print profile update so manually delete the template json file 
				if (strpos($eachModule, 'template') !== false) {
					$this->deleteAllTemplateCacheFile();
				}
			}

			if (!empty($printprofileArray)) {
				foreach ($printprofileArray as $printProfileId) {
					foreach ($modulesArray as $eachModule) {
						$cacheDir = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $printProfileId . "_" . $eachModule . '_cache.json';
						if (file_exists($cacheDir)) {
							unlink($cacheDir);
							$availablepp[] = $getParams['print_profile_id'];
						} else {
							$availablepp[] = $getParams['print_profile_id'];
						}

						// is_edit and is_cms key not available on print profile update so manually delete the template json file 
						if (strpos($eachModule, 'template') !== false) {
							$this->deleteAllTemplateCacheFile();
						}
					}
				}
			}
		}


		if (!empty($availablepp)) {
			$response = [
				'print_profile' => $availablepp,
				'page' => 1,
				'perpage' => ($moduleName == 'fonts') ? 20 : (($moduleName == 'clipart') ? 6 : 10)
			];
		}

		//Delete cache for is_cms = 1
		if (strpos($moduleName, 'template') !== false) {
			$this->deleteAllTemplateCacheFile();
		}

		return $response;
	}


	/**
	 * Internal function : save/get cache against a key
	 *
	 * @param $request  Slim's Request object
	 * @param $response Slim's Response object
	 *
	 * @author debashisd@riaxe.com
	 * @date   23 May 2024
	 * @return json response of success and failure message.
	 */
	public function memcache($action, $cacheKey, $data = "", $module = '', $selectedKeys = '')
	{
		$settingLocation = path('abs', 'setting') . 'memcached.xml';
		if (file_exists($settingLocation)) {
			$dom = new \DomDocument();
			$dom->load($settingLocation);
			$flag = $dom->getElementsByTagName('is_enabled')->item(0)->nodeValue;
			if ($flag == 1) {
				$memHost = $dom->getElementsByTagName('memhost')->item(0)->nodeValue;
				$memPort = $dom->getElementsByTagName('memport')->item(0)->nodeValue;
				$memcached = new \Memcached;
				$isMemcacheAvailable = $memcached->addServer($memHost, $memPort, 100);
				if ($isMemcacheAvailable) {
					switch ($action) {
						case 'set':
							$memcached->set($cacheKey, $data);
							return true;

						case 'get':
							return $memcached->get($cacheKey);

						case 'delete':
							return $memcached->delete($cacheKey);

						case 'deleteMulti':
							if (!empty($selectedKeys)) {
								$keys = $selectedKeys;
							} else {
								$keys = $this->createUpdateMemCacheGroup($module, '', 'GET');
							}

							if (!empty($keys)) {
								return $memcached->deleteMulti($keys);
							}
							return 1;

							//cases like flush, update etc might be written

						default:
							return true;
					}
				}
			}
		}
	}


	/**
	 * create Mamecached Key
	 *
	 * @param $request  
	 *
	 *
	 * @author steve@imprintnext.com
	 * @date   31 May 2024
	 */

	public function createUpdateMemCacheGroup($moduleName, $cacheKey, $mode = 'GET')
	{
		$cacheJsonFile = ASSETS_PATH_W . 'cache/design_assets/' . $moduleName . '_mem_cache.json';

		if (file_exists($cacheJsonFile)) {
			$assetCacheKeyArray = json_decode(file_get_contents($cacheJsonFile), true);
			if ($mode == 'GET') {
				$status = unlink($cacheJsonFile);
				return $assetCacheKeyArray;
			}

			if (!in_array($cacheKey, $assetCacheKeyArray)) {
				$assetCacheKeyArray[] = $cacheKey;
				file_put_contents($cacheJsonFile, json_encode($assetCacheKeyArray, true));
			}
		} else {
			$cacheDir = ASSETS_PATH_W . 'cache';
			if (!is_dir($cacheDir)) {
				mkdir($cacheDir, 0777, true);
			}
			$designAssetDir = $cacheDir . '/design_assets';
			if (!is_dir($designAssetDir)) {
				mkdir($designAssetDir, 0777, true);
			}
			file_put_contents($cacheJsonFile, json_encode([$cacheKey]));
		}
	}

	/**
	 * create/update asset categories json cache
	 *
	 * @param $request
	 *
	 *
	 * @author maria@imprintnext.com
	 * @date   11 july 2024
	 */
	public function createUpdateAssetJsonCache($storeId, $printProfileIdsArr, $moduleName, $request, $response)
	{
		foreach ($printProfileIdsArr as $printProfileId) {
			$params = [
				'store_id' => $storeId,
				'asset_slug' => $moduleName,
				'print_profile_id' =>  $printProfileId,
			];
			$request = $request->withQueryParams($params);
			$response = $this->getCategoryByPrintProfile($request, $response, '');
			$result = json_decode($response->getBody(), true);
			$assetCatData = json_encode($result, true);
			$cacheDir = ASSETS_PATH_W . 'cache';
			if (!is_dir($cacheDir)) {
				mkdir($cacheDir, 0777, true);
			}
			$designAssetDir = $cacheDir . '/design_assets';
			if (!is_dir($designAssetDir)) {
				mkdir($designAssetDir, 0777, true);
			}
			$cacheJsonFile = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $printProfileId . "_" . $moduleName . '_cat_cache.json';
			if (file_exists($cacheJsonFile)) {
				unlink($cacheJsonFile);
			}
			//file_put_contents($cacheJsonFile, $assetCatData);
		}
	}
	/**
	 * get asset categories json cache
	 *
	 * @param $request
	 *
	 *
	 * @author maria@imprintnext.com
	 * @date   11 july 2024
	 */
	public function getAssetCatCache($storeId, $printProfile, $moduleName)
	{
		//get asset categories cache
		$printProfileId = strlen($printProfile) > 1 ? json_decode($printProfile, true) : $printProfile;
		if (is_array($printProfileId)) {
			$printProfileId = $printProfileId[0];
		}
		$cacheJsonFile = ASSETS_PATH_W . 'cache/design_assets/' . $storeId . '_' . $printProfileId . "_" . $moduleName . '_cat_cache.json';
		if (file_exists($cacheJsonFile)) {
			$assetCatresponse = json_clean_decode(file_get_contents($cacheJsonFile), true);

			return $assetCatresponse;
		}
	}
	public function generateDesignFiles($jsonContent, $customDesignId)
	{
		$post['json_data'] = $jsonContent; // our data todo in received
		$post['custom_design_id'] = $customDesignId; // our data todo in received
		$createDesign = call_curl($post, "create-designs", "POST", false, false, false);
	}

	private function deleteAllTemplateCacheFile()
	{
		$cacheFolderPath = ASSETS_PATH_W . 'cache/design_assets/';

		if (is_dir($cacheFolderPath)) {
			// Get all JSON files in the folder with names containing 'template'
			$files = glob($cacheFolderPath . '*template*.json');

			// Loop through each file and delete it
			foreach ($files as $file) {
				if (is_file($file)) {
					unlink($file); // Delete the file
					//echo "Deleted: " . basename($file) . "\n";
				}
			}
		}
	}
	/**
	 * Encrypt string
	 *
	 * @param $urlToEncode
	 * @author soumyas@riaxe.com
	 * @date   09 Jan 2025
	 * @return string
	 */
	public function encryptKey($urlToEncode)
	{
		$enCodedBit = '';
		$encryptedTxt = '';
		$cipherKey = '5';
		$secretKey = "U8y/B?E(H+MbQeThWmYq3t6w9z^C&F)J@Nc";
		// Append the secret key to the URL
		$urlToEncode .= $secretKey;
		// Loop through each character of the string and encrypt it
		for ($i = 0; $i < strlen($urlToEncode); $i++) {
			// Shift the character code by the value of the cipher key
			$enCodedBit = chr(ord($urlToEncode[$i]) + ord($cipherKey));
			$encryptedTxt .= $enCodedBit;
		}
		// Base64 encode the result and prepend a "?" symbol
		$encryptedTxt = base64_encode($encryptedTxt);
		return $encryptedTxt;
	}
	/**
	 * Decrypt string
	 *
	 * @param $encryptedTxt
	 * @author soumyas@riaxe.com
	 * @date   09 Jan 2025
	 * @return string
	 */
	public function decryptKey($encryptedTxt)
	{
		$deCodedBit = '';
		$decryptedTxt = '';
		$cipherKey = '5';
		$secretKey = "U8y/B?E(H+MbQeThWmYq3t6w9z^C&F)J@Nc";
		// Base64 decode the encrypted text
		$decodedTxt = base64_decode($encryptedTxt);
		// Loop through each character of the decoded string to decrypt it
		for ($i = 0; $i < strlen($decodedTxt); $i++) {
			// Reverse the shift in the character code by the cipher key
			$deCodedBit = chr(ord($decodedTxt[$i]) - ord($cipherKey));
			$decryptedTxt .= $deCodedBit;
		}
		// Remove the secret key appended to the original URL
		if (substr($decryptedTxt, -strlen($secretKey)) === $secretKey) {
			$decryptedTxt = substr($decryptedTxt, 0, -strlen($secretKey));
		} else {
			return false; // Invalid encrypted text
		}
		return $decryptedTxt;
	}
	/**
	 * Get first N characters from a string
	 *
	 * @param $string
	 * @param $number
	 * @author soumyas@riaxe.com
	 * @date   09 Jan 2025
	 * @return string
	 */
	public function getFirstNCharacters($string, $number)
	{
		return substr($string, 0, $number);
	}
	/**
	 * Get last N characters from a string
	 *
	 * @param $string
	 * @param $number
	 * @author soumyas@riaxe.com
	 * @date   09 Jan 2025
	 * @return string
	 */
	public function getLastNCharacters($string, $number)
	{
		return substr($string, -$number);
	}
	/**
	 * Get SMTP password
	 *
	 * @param $settingKey
	 * @param $type
	 * @param $storeId
	 * @param $isDecryptPasseord
	 * @author soumyas@riaxe.com
	 * @date   09 Jan 2025
	 * @return string
	 */
	public function getSmtpPassword($settingKey, $type, $storeId, $isDecryptPasseord = 1)
	{
		$smtpPassword = '';
		$settingsInit = new \App\Modules\Settings\Models\Setting();
		$getSettings = $settingsInit->where([
			'setting_key' => $settingKey,
			'type' => $type,
			'store_id' => $storeId
		]);
		if ($getSettings->count() > 0) {
			$smtpEmailSettingData = $getSettings->first()->toArray();
			$smtpData = json_clean_decode($smtpEmailSettingData['setting_value'], true);
			if (!empty($smtpData['smtp_pass'])) {
				$smtpPassword = ($isDecryptPasseord == 1) ? $this->decryptKey($smtpData['smtp_pass']) : $smtpData['smtp_pass'];
			}
		}
		return $smtpPassword;
	}
	/**
	 * Get SMTP details
	 *
	 * @param $type
	 * @param $storeId
	 * @author soumyas@riaxe.com
	 * @date   09 Jan 2025
	 * @return Array
	 */
	public function getSmtpSettings($type, $storeId)
	{
		$smtpSetting = [];
		$settingsInit = new \App\Modules\Settings\Models\Setting();
		$getSettings = $settingsInit->where([
			'type' => $type,
			'store_id' => $storeId
		]);
		if ($getSettings->count() > 0) {
			$smtpEmailSettingData = $getSettings->get()->toArray();
			$smtpId = array_search('smtp_details', array_column($smtpEmailSettingData, 'setting_key'));
			$emailAddressId = array_search('email_address_details', array_column($smtpEmailSettingData, 'setting_key'));
			$emailAddressInfo = $smtpEmailSettingData[$emailAddressId];
			$emailData = json_clean_decode($emailAddressInfo['setting_value'], true);
			$smtpInfo = $smtpEmailSettingData[$smtpId];
			$smtpData = json_clean_decode($smtpInfo['setting_value'], true);
			$smtpData['smtp_pass'] = ($smtpData['smtp_pass']) ? $this->decryptKey($smtpData['smtp_pass']) : '';
			$smtpSetting['smtp_data'] = $smtpData;
			$smtpSetting['email_data'] = $emailData;
		}
		return $smtpSetting;
	}
}
