<?php
/*
 * Jetpack CRM
 * https://jetpackcrm.com
 * V3.0
 *
 * Copyright 2020 Automattic
 *
 * Date: 20/02/2019
 */

defined( 'ZEROBSCRM_PATH' ) || exit( 0 );

/*
======================================================
	Init Func
	====================================================== */

function zeroBSCRM_QuotesMetaboxSetup() {

	// main detail
	$zeroBS__Metabox_Quote = new zeroBS__Metabox_Quote( __FILE__ );

	// quote content box
	$zeroBS__Metabox_QuoteContent = new zeroBS__Metabox_QuoteContent( __FILE__ );

	// quote next step box (publish etc.)
	$zeroBS__Metabox_QuoteNextStep = new zeroBS__Metabox_QuoteNextStep( __FILE__ );

	// quote actions box
	$zeroBS__Metabox_QuoteActions = new zeroBS__Metabox_QuoteActions( __FILE__ );

	// quote tags box
	$zeroBS__Metabox_QuoteTags = new zeroBS__Metabox_QuoteTags( __FILE__ );

	// quote accepted details
	$zeroBS__Metabox_QuoteAcceptedDetails = new zeroBS__Metabox_QuoteAcceptedDetails( __FILE__ );

	// files
	$zeroBS__Metabox_QuoteFiles = new zeroBS__Metabox_QuoteFiles( __FILE__ );
}

	add_action( 'admin_init', 'zeroBSCRM_QuotesMetaboxSetup' );

	/*
		$zeroBS__MetaboxQuote = new zeroBS__MetaboxQuote( __FILE__ );
		$zeroBS__QuoteContentMetabox = new zeroBS__QuoteContentMetabox( __FILE__ );
		$zeroBS__QuoteActionsMetabox = new zeroBS__QuoteActionsMetabox( __FILE__ );
		$zeroBS__QuoteStatusMetabox = new zeroBS__QuoteStatusMetabox( __FILE__ );
	*/

/*
======================================================
	/ Init Func
	====================================================== */

/*
======================================================
	Quote Metabox
	====================================================== */

class zeroBS__Metabox_Quote extends zeroBS__Metabox {

	// this is for catching 'new' quotes
	private $newRecordNeedsRedir = false;

	public function __construct( $plugin_file ) {

		// set these
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-edit';
		$this->metaboxTitle    = __( 'Step 1: Quote Details', 'zero-bs-crm' ); // will be headless anyhow
		$this->headless        = true;
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit';
		$this->metaboxArea     = 'normal';
		$this->metaboxLocation = 'high';
		$this->saveOrder       = 1;
		$this->capabilities    = array(

			'can_hide'        => false, // can be hidden
			'areas'           => array( 'normal' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => true,  // can/can't accept tabs onto it
			'can_become_tab'  => false, // can be added as tab
			'can_minimise'    => true, // can be minimised
			'can_move'        => true, // can be moved

		);

		// call this
		$this->initMetabox();
	}

	public function html( $quote, $metabox ) {

			// localise ID
			$quoteID = -1;
		if ( is_array( $quote ) && isset( $quote['id'] ) ) {
			$quoteID = (int) $quote['id'];
		}

			// if new + $zbsObjDataPrefill passed, use that instead of loaded trans.
		if ( $quoteID == -1 ) {
			global $zbsObjDataPrefill;
			$quote = $zbsObjDataPrefill;
		}

			global $zbs;

			// Define Quote statuses.
			$acceptable_quote_statuses = jpcrm_get_quote_statuses();

			// status
			$status = $acceptable_quote_statuses['draft'];
		if ( is_array( $quote ) && isset( $quote['status'] ) ) {
			if ( $quote['status'] === -2 ) {
				$status = $acceptable_quote_statuses['published'];
			}
			if ( $quote['status'] === 1 ) {
				$status = $acceptable_quote_statuses['accepted'];
			}
		}
			// Debug echo 'Quote:<pre>'.print_r($quote,1).'</pre>';

		?>                
				<script type="text/javascript">var zbscrmjs_secToken = <?php echo wp_json_encode( wp_create_nonce( 'zbscrmjs-ajax-nonce' ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;</script>
				<?php

				#} retrieve
				// some legacy bits from CPT days:
				$quoteContactID = -1;
				if ( is_array( $quote ) && isset( $quote['contact'] ) && is_array( $quote['contact'] ) && count( $quote['contact'] ) > 0 ) {
					$quoteContactID = $quote['contact'][0]['id']; // get_post_meta($post->ID, 'zbs_customer_quote_customer', true);
				}
				$templateUsed = -1;
				if ( is_array( $quote ) && isset( $quote['template'] ) ) {
					$templateUsed = $quote['template']; // get_post_meta($post->ID, 'zbs_quote_template_id', true);
				}

				#} this is a temp weird one, just passing onto meta for now (long day):
				// ? Not used DAL3?
				// $zbsTemplated = get_post_meta($post->ID, 'templated', true);
				// if (!empty($zbsTemplated)) $quote['templated'] = true;
				// quick WH predictive hack, not sure if viable - to test DAL3
				$quote['templated'] = false;
				if ( $templateUsed !== -1 && ! empty( $templateUsed ) ) {
					$quote['templated'] = true;
				}

				#} if customer id is empty, but prefill isn't, use prefill
				if ( $quoteContactID == -1 && isset( $_GET['zbsprefillcust'] ) ) {
					$quoteContactID = (int) $_GET['zbsprefillcust'];
				}

				#} pass to other metaboxes (cache?)
				global $zbsCurrentEditQuote;
				$zbsCurrentEditQuote = $quote;

				#} Retrieve fields from global
				global $zbsCustomerQuoteFields;
				$fields = $zbsCustomerQuoteFields;
				// Debug echo 'Fields:<pre>'.print_r($fields,1).'</pre>';

				#} Using "Quote Builder" or not?
				$useQuoteBuilder = zeroBSCRM_getSetting( 'usequotebuilder' );

				// Inputs out:

				#} New quote?
				if ( ! isset( $quote['id'] ) ) {
					echo '<input type="hidden" name="zbscrm_newquote" value="1" />';
				}

				#} pass this if already templated:
				if ( $useQuoteBuilder == 1 && isset( $quote['template'] ) ) {
					echo '<input type="hidden" name="zbscrm_templated" id="zbscrm_templated" value="1" />';
				}

				#} Nonce used for loading quote template, left in for now, could be centralised to normal sec nonce
				echo '<input type="hidden" name="quo-ajax-nonce" id="quo-ajax-nonce" value="' . esc_attr( wp_create_nonce( 'quo-ajax-nonce' ) ) . '" />';

				// we pass the hash along the chain here too :)
				echo '<input type="hidden" name="zbscq_hash" id="zbscq_hash" value="' . ( isset( $quote['hash'] ) ? esc_attr( $quote['hash'] ) : '' ) . '" />';
				?>
					<div>
						<div class="jpcrm-form-grid" id="wptbpMetaBoxMainItem">
				<?php

				// DAL3 only show after saved, easier
				if ( ! empty( $quoteID ) && $quoteID > 0 ) {
					?>
								<div class="jpcrm-form-group jpcrm-form-group-span-2">
									<label class="jpcrm-form-label"><?php esc_html_e( 'Quote (ID)', 'zero-bs-crm' ); ?>:</label>
							<?php
								echo '<b>' . esc_html( $quoteID ) . '</b>'; //phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
							?>
									<input type="hidden" name="zbsquoteid" value="<?php echo esc_attr( $quoteID ); //phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase ?>" />
								</div>
							<?php

				}
				// Quote status.
				if ( $quoteID > 0 ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
					?>
				
					<div class="jpcrm-form-group jpcrm-form-group-span-2">
						<label class="jpcrm-form-label" for="quote_status"><?php esc_html_e( 'Status', 'zero-bs-crm' ); ?>:</label>
						<select class="form-control" id="quote_status" name="quote_status">
							<?php
							foreach ( $acceptable_quote_statuses as $status_opt => $status_str ) {
								$sel = '';
								if ( $status_str === $status ) {
									$sel = ' selected="selected"';
								}
								/* Translators:  %s is the Quote status. */
								echo '<option value="' . esc_attr( $status_opt ) . '"' . esc_attr( $sel ) . '>' . esc_html( sprintf( __( '%s', 'zero-bs-crm' ), $status_str ) ) . '</option>'; // phpcs:ignore WordPress.WP.I18n.NoEmptyStrings
							}
							?>
						</select>
					</div>
						<?php
				} // end if

				?>
						<div class="jpcrm-form-group jpcrm-form-group-span-2 jpcrm-override-typeahead-padding">
						<label class="jpcrm-form-label"><?php esc_html_e( 'Contact', 'zero-bs-crm' ); ?>:</label>
					<?php

					#} 27/09/16 - switched select for typeahead

						#} Any customer?
						$prefillStr = ''; if ( isset( $quoteContactID ) && ! empty( $quoteContactID ) ) {

							$prefillStr = $zbs->DAL->contacts->getContactNameWithFallback( $quoteContactID );

						}

						#} Output select box
						echo zeroBSCRM_CustomerTypeList( 'zbscrmjs_quoteCustomerSelect', $prefillStr, true, 'zbscrmjs_quote_unsetCustomer' );

						#} Output input which will pass the value via post
						?>
							<input type="hidden" name="zbscq_customer" id="zbscq_customer" value="<?php echo esc_attr( $quoteContactID ); ?>" />
							<?php

							#} Output function which will copy over value - maybe later move to js
							?>
							<script type="text/javascript">

								jQuery(function(){

									// bind 
									setTimeout(function(){
										zeroBSCRMJS_showContactLinkIf(jQuery("#zbscq_customer").val());
									},0);

								});

								function zbscrmjs_quoteCustomerSelect(cust){

									// pass id to hidden input
									jQuery('#zbscq_customer').val(cust.id);

									// enable/disable button if present (here is def present)
									jQuery('#zbsQuoteBuilderStep2').prop( 'disabled', false );
									jQuery('#zbsQuoteBuilderStep2info').hide();


									setTimeout(function(){

										var lID = cust.id;

										// when inv select drop down changed, show/hide quick nav
										zeroBSCRMJS_showContactLinkIf(lID);

									},0);

								}

								function zbscrmjs_quote_unsetCustomer(o){

									if (typeof o == "undefined" || o == ''){

										jQuery("#zbscq_customer").val('');
										//jQuery("#bill").val('');
										//jQuery("#cusbill").val('');

										setTimeout(function(){

											// when inv select drop down changed, show/hide quick nav
											zeroBSCRMJS_showContactLinkIf('');

										},0);
										
									}
								}

								// if an contact is selected (against a trans) can 'quick nav' to contact
								function zeroBSCRMJS_showContactLinkIf(contactID){

									// remove old
									//jQuery('#zbs-customer-title .zbs-view-contact').remove();
									jQuery('#zbs-quote-learn-nav .zbs-quote-quicknav-contact').remove();

									if (typeof contactID != "undefined" && contactID !== null && contactID !== ''){

										contactID = parseInt(contactID);
										if (contactID > 0){

											// seems like a legit inv, add

											/* this was from trans meta, here just add to top
												var html = '<div class="ui right floated mini animated button zbs-view-contact">';
														html += '<div class="visible content"><?php zeroBSCRM_slashOut( __( 'View', 'zero-bs-crm' ) ); ?></div>';
															html += '<div class="hidden content">';
																html += '<i class="user icon"></i>';
															html += '</div>';
														html += '</div>';

												jQuery('#zbs-customer-title').prepend(html); */

												// ALSO show in header bar, if so
																var navButton = '<a target="_blank" style="margin-left:6px;" class="zbs-quote-quicknav-contact ui icon button black mini labeled" href="<?php echo jpcrm_esc_link( 'edit', -1, 'zerobs_customer', true ); ?>' + contactID + '"><i class="user icon"></i> ' + <?php echo wp_json_encode( __( 'Contact', 'zero-bs-crm' ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?> + '</a>';
												jQuery('#zbs-quote-learn-nav').append(navButton);

												// bind
												//zeroBSCRMJS_bindContactLinkIf();
										}
									}

								}

							</script>
							</div>
						<?php

						// wh centralised 20/7/18 - 2.91+ skipFields
						zeroBSCRM_html_editFields( $quote, $fields, 'zbscq_' );

						#} if enabled, and new quote, or one which hasn't had the 'templated' meta key added.
						if ( $useQuoteBuilder == 1 && ! isset( $quote['template'] ) ) {
							?>
							<div class="jpcrm-form-group jpcrm-form-group-span-2">
							<div class="zbs-move-on-wrap">

								<!-- infoz -->
								<h3><?php esc_html_e( 'Publish this Quote', 'zero-bs-crm' ); ?></h3>
								<p><?php esc_html_e( 'Do you want to use the Quote Builder to publish this quote? (This lets you email it to a client directly, for approval)', 'zero-bs-crm' ); ?></p>

								<input type="hidden" name="zbs_quote_template_id_used" id="zbs_quote_template_id_used" value="<?php echo ! empty( $templateUsed ) ? esc_attr( $templateUsed ) : ''; ?>" />
								<select class="form-control" name="zbs_quote_template_id" id="zbs_quote_template_id">
									<option value="" disabled="disabled"><?php esc_html_e( 'Select a template', 'zero-bs-crm' ); ?>:</option>
									<?php

										$templates = zeroBS_getQuoteTemplates( true, 100, 0 );

										#} If this quote has already selected a template it'll be stored in the meta under 'templateid'
										#} But if it's not the first, we never need to show this anyway...

									if ( count( $templates ) > 0 ) {
										foreach ( $templates as $template ) {

											$templateName = __( 'Template', 'zero-bs-crm' ) . ' ' . $template['id'];
											if ( isset( $template['title'] ) && ! empty( $template['title'] ) ) {
												$templateName = $template['title'] . ' (' . $template['id'] . ')';
											}

											echo '<option value="' . esc_attr( $template['id'] ) . '"';
											#if (isset())
											echo '>' . esc_html( $templateName ) . '</option>';

										}
									}

									?>
									<option value=""><?php esc_html_e( 'Blank Template', 'zero-bs-crm' ); ?></option>
								</select>
								<br />
								<p>
									<?php esc_html_e( 'Create additional quote templates', 'zero-bs-crm' ); ?>
									<a href="<?php echo jpcrm_esc_link( $zbs->slugs['quote-templates'] ); ?>">
										<?php esc_html_e( 'here', 'zero-bs-crm' ); ?>
									</a>
								</p>
								<button type="button" id="zbsQuoteBuilderStep2" class="ui button button-primary black button-large xl"
									<?php disabled( $quoteContactID <= 0 ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase ?>><?php esc_html_e( 'Use Quote Builder', 'zero-bs-crm' ); ?>
								</button>
								<?php if ( $quoteContactID <= 0 ) { /* phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase, Squiz.ControlStructures.ControlSignature.NewlineAfterOpenBrace */ ?>
									<p id="zbsQuoteBuilderStep2info">(<?php esc_html_e( "You'll need to assign this Quote to a contact to use this", 'zero-bs-crm' ); ?>);</p>
								<?php } ?>

							</div>
						</div>
						<?php } ?>

						</div>
					</div>
				<?php
	}

	public function save_data( $quoteID, $quote ) {

		if ( ! defined( 'ZBS_OBJ_SAVED' ) ) {

			define( 'ZBS_OBJ_SAVED', 1 );

			// DAL3.0+
			global $zbs;

			// check this
			if ( empty( $quoteID ) || $quoteID < 1 ) {
				$quoteID = -1;
			}

				// defaults, pulled from DAL obj 25/2/19
				/*
					$quote = array(
					'title' => '',
					'currency' => '',
					'value' => '',
					'date' => '',
					'template' => '',
					'content' => '',
					'notes' => '',
					'send_attachments' => -1, (removed 4.0.9)
					'hash' => '',
					'lastviewed' => '',
					'viewed_count' => '',
					'accepted' => '',
					//'created' => '',
					//'lastupdated' => '',
				);
				*/
				$extraMeta = array(); // can pass any additional meta here

				// retrieve _POST into arr
				// global $zbsCustomerQuoteFields;
				// $zbsCustomerQuoteMeta = zeroBSCRM_save_fields($zbsCustomerQuoteFields,'zbscq_');
				$autoGenAutonumbers = true; // generate if not set :)
				$removeEmpties      = false; // req for autoGenAutonumbers
				$quote              = zeroBS_buildObjArr( $_POST, array(), 'zbscq_', '', $removeEmpties, ZBS_TYPE_QUOTE, $autoGenAutonumbers );

				// Use the tag-class function to retrieve any tags so we can add inline.
				// Save tags against objid
				$quote['tags'] = zeroBSCRM_tags_retrieveFromPostBag( true, ZBS_TYPE_QUOTE );

				// we always get this, because it's used below, but not part of buildObjArr (currently at 3.0)
			if ( $quoteID > 0 ) {
				$quote['template'] = (int) $zbs->DAL->quotes->getQuoteTemplateID( $quoteID );
			}

				// content (from other metabox actually)
			if ( isset( $_POST['zbs_quote_content'] ) ) {

				#} Save content
				// $data=htmlspecialchars($_POST['zbs_quote_content'], ENT_COMPAT);
				$quote['content'] = wp_kses( $_POST['zbs_quote_content'], $zbs->acceptable_html ); // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- to follow up with.
				#} update templated vars
				if ( isset( $_POST['zbs_quote_template_id'] ) ) {
					$quote['template'] = (int) sanitize_text_field( $_POST['zbs_quote_template_id'] );
				}
			}

				#} First up, save quote id! #TRANSITIONTOMETANO
				// DAL 3 will probs move away from this, for now leaving for refactoring round 2
				// for now store as meta (though perhaps needs a new field zbsid)
				$quoteOffset = zeroBSCRM_getQuoteOffset();
				$quoteZBSID  = (int) $quoteID + $quoteOffset;
			if ( isset( $_POST['zbsquoteid'] ) && ! empty( $_POST['zbsquoteid'] ) ) {
				$quoteZBSID = (int) $_POST['zbsquoteid'];
			}
				// update_post_meta($post_id,"zbsid",$quoteID);
				$extraMeta['zbsid'] = $quoteZBSID;
				#} and increment this
			if ( ! empty( $quoteZBSID ) ) {
				zeroBSCRM_setMaxQuoteID( $quoteZBSID );
			}

				// assignments
				$zbsQuoteContact = -1;
			if ( isset( $_POST['zbscq_customer'] ) ) {
				$zbsQuoteContact = (int) sanitize_text_field( $_POST['zbscq_customer'] );
			}
				$quote['contacts'] = ( $zbsQuoteContact > 0 ) ? array( $zbsQuoteContact ) : array();
				$zbsQuoteCompany   = -1;
			if ( isset( $_POST['zbscq_company'] ) ) {
				$zbsQuoteCompany = (int) sanitize_text_field( $_POST['zbscq_company'] );
			}
				$quote['companies'] = ( $zbsQuoteCompany > 0 ) ? array( $zbsQuoteCompany ) : array();

				/*
					line item (temp here from Inv metabox, not yet implemented in ui)
				//new way..  now not limited to 30 lines as now they are stored in [] type array in JS draw
				$zbsInvoiceLines = array();
				foreach($_POST['zbsli_itemname'] as $k => $v){

					$ks = sanitize_text_field( $k ); // at least this

					$zbsInvoiceLines[$ks]['title']      = sanitize_text_field($_POST['zbsli_itemname'][$k]);
					$zbsInvoiceLines[$ks]['desc']           = sanitize_text_field($_POST['zbsli_itemdes'][$k]);
					$zbsInvoiceLines[$ks]['quantity']          = sanitize_text_field($_POST['zbsli_quan'][$k]);
					$zbsInvoiceLines[$ks]['price']         = sanitize_text_field($_POST['zbsli_price'][$k]);
					$zbsInvoiceLines[$ks]['tax']           = sanitize_text_field($_POST['zbsli_tax'][$k]);

				}
				if (count($zbsInvoiceLines) > 0) $invoice['lineitems'] = $zbsInvoiceLines;
				*/

				// Status Overwrites (manual changes, only after initial save)
			if ( $quoteID > 0 && isset( $_POST['quote_status'] ) ) {

				switch ( $_POST['quote_status'] ) {

					case 'draft':
						// if changing to draft, remove any accepted date + template ID
						$quote['accepted'] = 0;
						$quote['template'] = -1;

						break;
					case 'published':
						// if changing to published, just needs accepted unsetting, and if no template, populate
						$quote['accepted'] = 0;

						// got template?

							// if not already set, set, otherwise leave existing set time in.
						if ( ! isset( $quote['template'] ) || $quote['template'] <= 0 ) {

							// hacky setting of it to unlikely cieling
							$quote['template'] = 99999;

						}

						break;
					case 'accepted':
						// if not already accepted, mark accepted.

							// existing
							$accepted = (int) $zbs->DAL->quotes->getQuoteAcceptedTime( $quoteID );

							// if not already set, set, otherwise leave existing set time in.
						if ( $accepted <= 0 ) {

							// set it (first time, manual)
							$quote['accepted']       = time();
							$quote['acceptedsigned'] = 'manual';
							$quote['acceptedip']     = '';

						}

						break;

				}
			}

				// add/update
				$addUpdateReturn = $zbs->DAL->quotes->addUpdateQuote(
					array(

						'id'            => $quoteID,
						'data'          => $quote,
						'extraMeta'     => $extraMeta,
						'limitedFields' => -1,

					)
				);

			// Note: For NEW objs, we make sure a global is set here, that other update funcs can catch
			// ... so it's essential this one runs first!
			// this is managed in the metabox Class :)
			if ( $quoteID == -1 && ! empty( $addUpdateReturn ) && $addUpdateReturn != -1 ) {

				$quoteID = $addUpdateReturn;
				global $zbsJustInsertedMetaboxID;
				$zbsJustInsertedMetaboxID = $quoteID;

				// set this so it redirs
				$this->newRecordNeedsRedir = true;
			}

			// success?
			if ( $addUpdateReturn != -1 && $addUpdateReturn > 0 ) {

				// Update Msg
				// this adds an update message which'll go out ahead of any content
				// This adds to metabox: $this->updateMessages['update'] = zeroBSCRM_UI2_messageHTML('info olive mini zbs-not-urgent',__('Contact Updated',"zero-bs-crm"),'','address book outline','contactUpdated');
				// This adds to edit page
				$this->updateMessage();

				// catch any non-critical messages
				$nonCriticalMessages = $zbs->DAL->getErrors( ZBS_TYPE_QUOTE );
				if ( is_array( $nonCriticalMessages ) && count( $nonCriticalMessages ) > 0 ) {
					$this->dalNoticeMessage( $nonCriticalMessages );
				}
			} else {

				// fail somehow
				$failMessages = $zbs->DAL->getErrors( ZBS_TYPE_QUOTE );

				// show msg (retrieved from DAL err stack)
				if ( is_array( $failMessages ) && count( $failMessages ) > 0 ) {
					$this->dalErrorMessage( $failMessages );
				} else {
					$this->dalErrorMessage( array( __( 'Insert/Update Failed with general error', 'zero-bs-crm' ) ) );
				}

				// pass the pre-fill:
				global $zbsObjDataPrefill;
				$zbsObjDataPrefill = $quote;

			}
		}

		return $quote;
	}

	// This catches 'new' contacts + redirs to right url
	public function post_save_data( $objID, $obj ) {

		if ( $this->newRecordNeedsRedir ) {

			global $zbsJustInsertedMetaboxID;
			if ( ! empty( $zbsJustInsertedMetaboxID ) && $zbsJustInsertedMetaboxID > 0 ) {

				// redir
				wp_redirect( jpcrm_esc_link( 'edit', $zbsJustInsertedMetaboxID, $this->objType ) );
				exit( 0 );

			}
		}
	}

	public function updateMessage() {

		global $zbs;

		// zbs-not-urgent means it'll auto hide after 1.5s
		// genericified from DAL3.0
		$msg = zeroBSCRM_UI2_messageHTML( 'info olive mini zbs-not-urgent', $zbs->DAL->typeStr( $zbs->DAL->objTypeKey( $this->objType ) ) . ' ' . __( 'Updated', 'zero-bs-crm' ), '', 'address book outline', 'contactUpdated' );

		$zbs->pageMessages[] = $msg;
	}
}

/*
======================================================
	/ Quote Metabox
	====================================================== */

/*
======================================================
	Quote Content Metabox
	====================================================== */

class zeroBS__Metabox_QuoteContent extends zeroBS__Metabox {

	public function __construct( $plugin_file ) {

		// set these
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-content-edit';
		$this->metaboxTitle    = __( 'Step 2: Quote Content', 'zero-bs-crm' ); // will be headless anyhow
		$this->headless        = true;
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit';
		$this->metaboxArea     = 'normal';
		$this->metaboxLocation = 'low';
		$this->saveOrder       = 1;
		$this->capabilities    = array(

			'can_hide'        => false, // can be hidden
			'areas'           => array( 'normal' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => true,  // can/can't accept tabs onto it
			'can_become_tab'  => false, // can be added as tab
			'can_minimise'    => true, // can be minimised
			'can_move'        => true, // can be moved

		);

		// call this
		$this->initMetabox();
	}

	public function html( $quote, $metabox ) {

		global $zbs;

		// localise ID & content
		$quoteID = -1;
		if ( is_array( $quote ) && isset( $quote['id'] ) ) {
			$quoteID = (int) $quote['id'];
		}
		$quote_content = '';
		if ( is_array( $quote ) && isset( $quote['content'] ) ) {
			$quote_content = wp_kses( $quote['content'], $zbs->acceptable_html );
		}

		// remove "Add contact form" button from Jetpack
		remove_action( 'media_buttons', 'grunion_media_button', 999 );
		wp_editor(
			$quote_content,
			'zbs_quote_content',
			array(
				'editor_height' => 580,
				'wpautop'       => false,
			)
		);
	}

	// saved via main metabox
}

/*
======================================================
	/ Quote Content Metabox
	====================================================== */

/*
======================================================
	Quote Next Step Metabox
	====================================================== */

class zeroBS__Metabox_QuoteNextStep extends zeroBS__Metabox {

	public function __construct( $plugin_file ) {

		// set these
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-nextstep';
		$this->metaboxTitle    = __( 'Step 3: Publish and Send', 'zero-bs-crm' ); // will be headless anyhow
		$this->headless        = true;
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit';
		$this->metaboxArea     = 'normal';
		$this->metaboxLocation = 'low';
		$this->saveOrder       = 1;
		$this->capabilities    = array(

			'can_hide'        => false, // can be hidden
			'areas'           => array( 'normal' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => true,  // can/can't accept tabs onto it
			'can_become_tab'  => false, // can be added as tab
			'can_minimise'    => true, // can be minimised
			'can_move'        => true, // can be moved

		);

		// call this
		$this->initMetabox();
	}

	public function html( $quote, $metabox ) {

		if ( $quote === false ) {
			$quote = array();
		}
		global $zbs;

		// localise ID & content
		$quoteID = -1;
		if ( is_array( $quote ) && isset( $quote['id'] ) ) {
			$quoteID = (int) $quote['id'];
		}

		#} retrieve
		// some legacy bits from CPT days:
		$quoteContactID = -1;
		if ( is_array( $quote ) && isset( $quote['contact'] ) && is_array( $quote['contact'] ) && count( $quote['contact'] ) > 0 ) {
			$quoteContactID = $quote['contact'][0]['id']; // get_post_meta($post->ID, 'zbs_customer_quote_customer', true);
		}
		$templateUsed = -1;
		if ( is_array( $quote ) && isset( $quote['template'] ) ) {
			$templateUsed = $quote['template']; // get_post_meta($post->ID, 'zbs_quote_template_id', true);
		}

		#} Using "Quote Builder" or not?
		$useQuoteBuilder = zeroBSCRM_getSetting( 'usequotebuilder' );
		$useHash         = zeroBSCRM_getSetting( 'easyaccesslinks' );

		#} if enabled, and new quote, or one which hasn't had the 'templated' meta key added.
		if ( $useQuoteBuilder == '1' ) {

			// retrieve email $contactEmail = '';
			$contactEmail = $zbs->DAL->contacts->getContactEmail( $quoteContactID );// zeroBS_contactEmail($quoteContactID);

			// quick WH predictive hack, not sure if viable - to test DAL3
			$quote['templated'] = false;
			if ( $templateUsed !== -1 && ! empty( $templateUsed ) ) {
				$quote['templated'] = true;
			}

			#} first load?
			if ( gettype( $quote ) != 'array' || ! isset( $quote['templated'] ) ) {

				?>
							<div class="zbs-move-on-wrap" style="padding-top:30px;">

								<!-- infoz -->
								<h3><?php esc_html_e( 'Publish this Quote', 'zero-bs-crm' ); ?></h3>
								<p><?php esc_html_e( "When you've finished writing your Quote, save it here before sending on to your contact", 'zero-bs-crm' ); ?>:</p>

								<button type="button" id="zbsQuoteBuilderStep3" class="button button-primary button-large xl"><?php esc_html_e( 'Save Quote', 'zero-bs-crm' ); ?></button>

							</div>

						<?php

			} else {

				# already has a saved quote
				#} If Portal is uninstalled it will break Quotes. So show a message warning them that this should be on
				if ( ! zeroBSCRM_isExtensionInstalled( 'portal' ) ) {
					?>
							<div class="ui message red" style="font-size:18px;">
								<b><i class="ui icon warning"></i><?php esc_html_e( 'Client Portal Deactivated', 'zero-bs-crm' ); ?></b>
								<p><?php esc_html_e( 'You have uninstalled the Client Portal. The only way you will be able to send your Quote to your contact is by downloading a PDF (needs PDF invoicing installed) and then emailing it to them manually.', 'zero-bs-crm' ); ?></p>
								<a class="ui button blue" href="<?php echo esc_url( admin_url( 'admin.php?page=zerobscrm-extensions' ) ); ?>"><?php esc_html_e( 'Enable Client Portal', 'zero-bs-crm' ); ?></a>
							</div>
						<?php
				} else {

					// v3.0+ we use hash urls, so check exists
					$dal3HashCheck = true;
					if ( ( ! isset( $quote['hash'] ) || empty( $quote['hash'] ) ) ) {
						$dal3HashCheck = false; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
					}

					if ( isset( $contactEmail ) && ! empty( $contactEmail ) && zeroBSCRM_validateEmail( $contactEmail ) && ( ! $useHash || ( $useHash && $dal3HashCheck ) ) ) {

						// has email, and portal, all good

						?>

								<div class="zbs-move-on-wrap" style="padding-top:30px;">
								<?php
									#} Add nonce
									echo '<script type="text/javascript">var zbscrmjs_secToken = ' . wp_json_encode( wp_create_nonce( 'zbscrmjs-ajax-nonce' ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';</script>';
								?>

									<!-- infoz -->
									<h3><?php esc_html_e( 'Email or Share', 'zero-bs-crm' ); ?></h3>
									<p><?php esc_html_e( 'Great! Your Quote has been published. You can now email it to your contact, or share the link directly', 'zero-bs-crm' ); ?>:</p>

									<?php do_action( 'zbs_quote_actions' ); ?>

									<div class="zbsEmailOrShare">
										<h4><?php esc_html_e( 'Email to Contact', 'zero-bs-crm' ); ?>:</h4>
										<!-- todo -->                                    
										<p><input type="text" class="form-control" id="zbsQuoteBuilderEmailTo" value="<?php echo esc_attr( $contactEmail ); ?>" placeholder="<?php esc_attr_e( 'e.g. customer@yahoo.com', 'zero-bs-crm' ); ?>" data-quoteid="<?php echo esc_attr( $quoteID ); ?>" /></p>
													<p><button type="button" id="zbsQuoteBuilderSendNotification" class="ui button black"><?php esc_html_e( 'Send Quote', 'zero-bs-crm' ); ?></button></p>
										<p class="small" id="zbsQuoteBuilderEmailToErr" style="display:none"><?php esc_html_e( 'An Email Address to send to is required', 'zero-bs-crm' ); ?>!</p>
									</div>
											<?php
											if ( property_exists( $zbs->modules, 'portal' ) ) :
												$quote_id_or_hash  = $useHash ? $quote['hash'] : $quoteID;
												$single_quote_slug = $zbs->modules->portal->get_endpoint( ZBS_TYPE_QUOTE );
												$preview_url       = zeroBS_portal_link( $single_quote_slug, $quote_id_or_hash );

												?>
									<div class="zbsEmailOrShare">
											<h4><?php esc_html_e( 'Share the Link or', 'zero-bs-crm' ); ?> <a href="<?php echo esc_url( $preview_url ); ?>" target="_blank"><?php esc_html_e( 'preview', 'zero-bs-crm' ); ?></a>:</h4>
											<p><input type="text" class="form-control" id="zbsQuoteBuilderURL" value="<?php echo esc_url( $preview_url ); ?>" /></p>
									</div>  
												<?php
													endif;
											?>

									<?php
									#} WH second change, only showed if dompdf extension installed
									if ( zeroBSCRM_isExtensionInstalled( 'pdfinv' ) ) {

										#} PDF Invoicing is installed
										?>
												<div class="zbsEmailOrShare">
												<h4><?php esc_html_e( 'Download PDF', 'zero-bs-crm' ); ?></h4>
												<p><i class="file pdf outline icon red" style="font-size:30px;margin-top:10px;"></i></p>
																<input type="button" name="jpcrm_quote_download_pdf" id="jpcrm_quote_download_pdf" class="ui button black" value="<?php esc_attr_e( 'Download PDF', 'zero-bs-crm' ); ?>" />
											   
												</div>
												<script type="text/javascript">
												jQuery(function(){

													// add your form to the end of body (outside <form>)
													var formHTML = '<form target="_blank" method="post" id="jpcrm_quote_download_pdf_form" action="">';
														formHTML += '<input type="hidden" name="jpcrm_quote_download_pdf" value="1" />';
														formHTML += '<input type="hidden" name="jpcrm_quote_id" value="<?php echo esc_attr( $quoteID ); ?>" />';
														formHTML += '<input type="hidden" name="jpcrm_quote_pdf_gen_nonce" value="<?php echo esc_attr( wp_create_nonce( 'jpcrm-quote-pdf-gen' ) ); ?>" />';
														formHTML += '</form>';
													jQuery('#wpbody').append(formHTML);

													// on click
													jQuery('#jpcrm_quote_download_pdf').on( 'click', function(){

														// submit form
														jQuery('#jpcrm_quote_download_pdf_form').submit();

													});

												});                    
												</script>
											<?php

									}
									?>
								
								</div>

							<?php

					} elseif ( isset( $quoteContactID ) && $quoteContactID > 0 ) {

							// Contact, but they don't have an email addr on file:
						?>

								<div class="zbs-move-on-wrap" style="padding-top:30px;">

									<h3><?php esc_html_e( 'Email or Share', 'zero-bs-crm' ); ?></h3>
									<div class="zbsEmailOrShare">
										<h4><?php esc_html_e( "Add Contact's Email", 'zero-bs-crm' ); ?>:</h4>
										<p><?php esc_html_e( 'To proceed, edit the contact and add their email address, that way we can then send them this quote online.', 'zero-bs-crm' ); ?></p>
										<p><a href="<?php echo jpcrm_esc_link( 'edit', $quoteContactID, 'zerobs_customer', true ); ?>" class="button button-primary button-large"><?php esc_html_e( 'Edit Contact', 'zero-bs-crm' ); ?></a></p>
									</div>              

								</div>

							<?php
					} else {

						// not yet assigned to anyone.
						?>

								<div class="zbs-move-on-wrap" style="padding-top:30px;">

									<h3><?php esc_html_e( 'Email or Share', 'zero-bs-crm' ); ?></h3>
									<div class="zbsEmailOrShare">
										<h4><?php esc_html_e( 'Assign to Contact', 'zero-bs-crm' ); ?>:</h4>
										<p><?php esc_html_e( 'To proceed, assign this quote to a contact and save it.', 'zero-bs-crm' ); ?></p>
									</div>              

								</div>

							<?php

					}
				}
			}
		} # if quotebuilder
	}

	// nothing to save.
}

/*
======================================================
	/ Quote Actions Metabox
	====================================================== */

/*
======================================================
	Quote files Metabox
	====================================================== */

class zeroBS__Metabox_QuoteFiles extends zeroBS__Metabox {

	public function __construct( $plugin_file ) {

		// DAL3 switched for objType $this->postType = 'zerobs_customer';
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-files';
		$this->metaboxTitle    = __( 'Associated Files', 'zero-bs-crm' );
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit'; // 'zerobs_edit_contact'; // we can use anything here as is now using our func
		$this->metaboxArea     = 'normal';
		$this->metaboxLocation = 'low';
		$this->capabilities    = array(

			'can_hide'        => true, // can be hidden
			'areas'           => array( 'normal' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => true,  // can/can't accept tabs onto it
			'can_become_tab'  => true, // can be added as tab
			'can_minimise'    => true, // can be minimised

		);

		// call this
		$this->initMetabox();
	}

	public function html( $quote, $metabox ) {

			global $zbs;

			$html = '';

			// localise ID
			$quoteID = -1;
		if ( is_array( $quote ) && isset( $quote['id'] ) ) {
			$quoteID = (int) $quote['id'];
		}

			#} retrieve
			$zbsFiles = array();
		if ( $quoteID > 0 ) {
			$zbsFiles = zeroBSCRM_files_getFiles( 'quote', $quoteID );
		}

		?>
				<table class="form-table wh-metatab wptbp" id="wptbpMetaBoxMainItemFiles">

				<?php

					// WH only slightly updated this for DAL3 - could do with a cleanup run (contact file edit has more functionality)

					#} Any existing
				if ( is_array( $zbsFiles ) && count( $zbsFiles ) > 0 ) {
					?>
							<tr class="wh-large"><th><label><?php printf( esc_html( _n( '%s associated file', '%s associated files', count( $zbsFiles ), 'text-domain' ) ), esc_html( number_format_i18n( count( $zbsFiles ) ) ) ); ?></label></th>
									<td id="zbsFileWrapInvoices">
								<?php
									$fileLineIndx = 1; foreach ( $zbsFiles as $zbsFile ) {

										$file = zeroBSCRM_files_baseName( $zbsFile['file'], isset( $zbsFile['priv'] ) );

										echo '<div class="zbsFileLine" id="zbsFileLineQuote' . esc_attr( $fileLineIndx ) . '"><a href="' . esc_url( $zbsFile['url'] ) . '" target="_blank">' . esc_html( $file ) . '</a> (<span class="zbsDelFile" data-delurl="' . esc_attr( $zbsFile['url'] ) . '"><i class="fa fa-trash"></i></span>)</div>';
										++$fileLineIndx;

									}
									?>
									</td></tr>
									<?php

				}
				?>

					<?php
					#adapted from http://code.tutsplus.com/articles/attaching-files-to-your-posts-using-wordpress-custom-meta-boxes-part-1--wp-22291

						$html .= '<input type="file" id="zbsobj_file_attachment" name="zbsobj_file_attachment" size="25" class="zbs-dc">';

					?>
							<tr class="wh-large"><th><label><?php esc_html_e( 'Add File', 'zero-bs-crm' ); ?>:</label><br />(<?php esc_html_e( 'Optional', 'zero-bs-crm' ); ?>)<br /><?php esc_html_e( 'Accepted File Types', 'zero-bs-crm' ); ?>:<br /><?php echo esc_html( zeroBS_acceptableFileTypeListStr() ); ?></th>
								<td>
								<?php
								wp_nonce_field( plugin_basename( __FILE__ ), 'zbsobj_file_attachment_nonce' );
								echo $html;
								?>
					</td></tr>
		
			</table>
			<?php
			$jpcrm_metabox_files_lang = array(
				'err'         => __( 'Error', 'zero-bs-crm' ),
				'unabletodel' => __( 'Unable to delete this file', 'zero-bs-crm' ),
			);
			?>
			<script type="text/javascript">

				var zbsQuotesCurrentlyDeleting = false;
				var zbsMetaboxFilesLang = <?php echo wp_json_encode( $jpcrm_metabox_files_lang, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;

				jQuery(function(){

					jQuery('.zbsDelFile').on( 'click', function(){

						if (!window.zbsQuotesCurrentlyDeleting){

							// blocking
							window.zbsQuotesCurrentlyDeleting = true;

							var delUrl = jQuery(this).attr('data-delurl');
							var lineIDtoRemove = jQuery(this).closest('.zbsFileLine').attr('id');

							if (typeof delUrl != "undefined" && delUrl != ''){



									// postbag!
									var data = {
									'action': 'delFile',
									'zbsfType': 'quotes',
									'zbsDel':  delUrl, // could be csv, never used though
									'zbsCID': <?php echo (int) $quoteID; ?>,
									'sec': window.zbscrmjs_secToken
									};

									// Send it Pat :D
									jQuery.ajax({
											type: "POST",
											url: ajaxurl, // admin side is just ajaxurl not wptbpAJAX.ajaxurl,
											"data": data,
											dataType: 'json',
											timeout: 20000,
											success: function(response) {

											// visually remove
											jQuery('#' + lineIDtoRemove).remove();

											// file deletion errors, show msg:
											if (typeof response.errors != "undefined" && response.errors.length > 0){

												jQuery.each(response.errors,function(ind,ele){

													jQuery('#zerobs-quotes-files-box').append('<div class="ui warning message" style="margin-top:10px;">' + ele + '</div>');

												});
													 
											}


											},
											error: function(response){

											jQuery('#zerobs-quotes-files-box').append('<div class="ui warning message" style="margin-top:10px;"><strong>' + window.zbsMetaboxFilesLang.err + ':</strong> ' + window.zbsMetaboxFilesLang.unabletodel + '</div>');

											}

										});

							}

							window.zbsQuotesCurrentlyDeleting = false;

						} // / blocking

					});

				});


			</script>
			<?php
	}

	public function save_data( $quoteID, $quote ) {

		global $zbsobj_justUploadedObjFile;
		$id = $quoteID;

		if ( ! empty( $_FILES['zbsobj_file_attachment']['name'] ) &&
			( ! isset( $zbsobj_justUploadedObjFile ) ||
				( isset( $zbsobj_justUploadedObjFile ) && $zbsobj_justUploadedObjFile != $_FILES['zbsobj_file_attachment']['name'] )
			)
			) {

			/* --- security verification --- */
			if ( ! wp_verify_nonce( $_POST['zbsobj_file_attachment_nonce'], plugin_basename( __FILE__ ) ) ) {
				return $id;
			} // end if

			if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
				return $id;
			} // end if

			if ( ! zeroBSCRM_permsQuotes() ) {
				return $id;
			}
			/* - end security verification - */

			// Blocking repeat-upload bug
			$zbsobj_justUploadedObjFile = $_FILES['zbsobj_file_attachment']['name'];

			// verify file extension and mime type
			if ( jpcrm_file_check_mime_extension( $_FILES['zbsobj_file_attachment'] ) ) {

				$quote_dir_info = jpcrm_storage_dir_info_for_quotes( $quoteID );
				if ( ! $quote_dir_info ) {
					wp_die( 'Could not prepare upload directory.' );
				}

				$upload = jpcrm_save_admin_upload_to_folder( 'zbsobj_file_attachment', $quote_dir_info['files'] );
				if ( isset( $upload['error'] ) && $upload['error'] != 0 ) {
					wp_die( 'There was an error uploading your file. The error is: ' . esc_html( $upload['error'] ) );
				} else {
						// w mod - adds to array :)
						$zbsFiles = zeroBSCRM_files_getFiles( 'quote', $quoteID );

					if ( is_array( $zbsFiles ) ) {

						// add it
						$zbsFiles[] = $upload;

					} else {

						// first
						$zbsFiles = array( $upload );

					}

						// update
						zeroBSCRM_files_updateFiles( 'quote', $quoteID, $zbsFiles );

						// Fire any 'post-upload-processing' (e.g. CPP makes thumbnails of pdf, jpg, etc.)
						// not req invoicing: do_action('zbs_post_upload_contact',$upload);
				}
			} else {
				wp_die( "The file type that you've uploaded is not an accepted file format." );
			}
		}

		return $quote;
	}
}

/*
======================================================
	/ Attach files to quote metabox
	====================================================== */

/*
======================================================
	Quote Accepted Details Metabox
	====================================================== */

class zeroBS__Metabox_QuoteAcceptedDetails extends zeroBS__Metabox {

	// this is for catching 'new' contacts
	private $newRecordNeedsRedir = false;

	public function __construct( $plugin_file ) {

		// set these
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-status-edit';
		$this->metaboxTitle    = __( 'Quote Public Status', 'zero-bs-crm' ); // will be headless anyhow
		$this->headless        = true;
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit';
		$this->metaboxArea     = 'side';
		$this->metaboxLocation = 'low';
		$this->saveOrder       = 1;
		$this->capabilities    = array(

			'can_hide'        => false, // can be hidden
			'areas'           => array( 'side' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => true,  // can/can't accept tabs onto it
			'can_become_tab'  => false, // can be added as tab
			'can_minimise'    => true, // can be minimised
			'can_move'        => true, // can be moved

		);

		global $useQuoteBuilder;

		// call this
		if ( $useQuoteBuilder == '1' ) {
			$this->initMetabox();
		}
	}

	public function html( $quote, $metabox ) {

		// localise ID & template
		$quoteID = -1;
		if ( is_array( $quote ) && isset( $quote['id'] ) ) {
			$quoteID = (int) $quote['id'];
		}
		$templateUsed = -1;
		if ( is_array( $quote ) && isset( $quote['template'] ) ) {
			$templateUsed = $quote['template'];
		}

		// quick WH predictive hack, not sure if viable - to test DAL3
		$quote['templated'] = false;
		if ( $templateUsed !== -1 && ! empty( $templateUsed ) ) {
			$quote['templated'] = true;
		}

		global $useQuoteBuilder;

		#} if enabled, and new quote, or one which hasn't had the 'templated' meta key added.
		#} ... also hide unless it's been "published"
		if ( $useQuoteBuilder == '1' && ( is_array( $quote ) && isset( $quote['templated'] ) && $quote['templated'] ) ) {

			if ( isset( $quote ) && is_array( $quote ) && isset( $quote['accepted'] ) && $quote['accepted'] > 0 ) {

				#} Deets
				$acceptedDate = date( zeroBSCRM_getTimeFormat() . ' ' . zeroBSCRM_getDateFormat(), $quote['accepted'] );
				$acceptedBy   = $quote['acceptedsigned'];
				$acceptedIP   = $quote['acceptedip'];

				?>

						<table class="wh-metatab-side wptbp" id="wptbpMetaBoxQuoteStatus">
							<tr><td style="text-align:center;color:green"><strong><?php esc_html_e( 'Accepted', 'zero-bs-crm' ); ?> <?php echo esc_html( $acceptedDate ); ?></strong></td></tr>
					<?php
					if ( ! empty( $acceptedBy ) ) {
						?>
						<tr><td style="text-align:center"><?php esc_html_e( 'By: ', 'zero-bs-crm' ); ?> <a href="mailto:<?php echo esc_attr( $acceptedBy ); ?>" target="_blank"
						<?php
						if ( ! empty( $acceptedIP ) ) {
												echo ' title="IP address:' . esc_attr( $acceptedIP ) . '"'; }
						?>
><?php echo esc_html( $acceptedBy ); ?></a></td></tr><?php } ?>                            
						</table>   

				<?php

			} else {

				?>

						<table class="wh-metatab-side wptbp" id="wptbpMetaBoxQuoteStatus">
							<tr>
							<td style="text-align:center"><strong><?php esc_html_e( 'Not Yet Accepted', 'zero-bs-crm' ); ?></td></tr>
						</table>  

					<?php

			}
		} else { // / only load if post type

			#} Gross hide :/
			?>
				<style type="text/css">#wpzbscquote_status {display:none;}</style>
				<?php

		}
	}

	// nothing to save
}

/*
======================================================
	/ Quote Accepted Details Metabox
	====================================================== */

/*
======================================================
	Create Tags Box
	====================================================== */

class zeroBS__Metabox_QuoteTags extends zeroBS__Metabox_Tags {

	public function __construct( $plugin_file ) {

		$this->objTypeID = ZBS_TYPE_QUOTE;
		// DAL3 switched for objType $this->postType = 'zerobs_customer';
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-tags';
		$this->metaboxTitle    = __( 'Quote Tags', 'zero-bs-crm' );
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit'; // 'zerobs_edit_contact'; // we can use anything here as is now using our func
		$this->metaboxArea     = 'side';
		$this->metaboxLocation = 'high';
		$this->showSuggestions = true;
		$this->capabilities    = array(

			'can_hide'        => true, // can be hidden
			'areas'           => array( 'side' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => false,  // can/can't accept tabs onto it
			'can_become_tab'  => false, // can be added as tab
			'can_minimise'    => true, // can be minimised

		);

		// call this
		$this->initMetabox();
	}

	// html + save dealt with by parent class :)
}

/*
======================================================
	/ Create Tags Box
	====================================================== */

/*
======================================================
	Quote Actions Metabox
	====================================================== */

class zeroBS__Metabox_QuoteActions extends zeroBS__Metabox {

	public function __construct( $plugin_file ) {

		// set these
		$this->objType         = 'quote';
		$this->metaboxID       = 'zerobs-quote-actions';
		$this->metaboxTitle    = __( 'Quote Actions', 'zero-bs-crm' ); // will be headless anyhow
		$this->headless        = true;
		$this->metaboxScreen   = 'zbs-add-edit-quote-edit';
		$this->metaboxArea     = 'side';
		$this->metaboxLocation = 'high';
		$this->saveOrder       = 1;
		$this->capabilities    = array(

			'can_hide'        => false, // can be hidden
			'areas'           => array( 'high' ), // areas can be dragged to - normal side = only areas currently
			'can_accept_tabs' => true,  // can/can't accept tabs onto it
			'can_become_tab'  => false, // can be added as tab
			'can_minimise'    => true, // can be minimised
			'can_move'        => true, // can be moved

		);

		// call this
		$this->initMetabox();
	}

	public function html( $quote, $metabox ) {

		?>
			<div class="zbs-generic-save-wrap">

					<div class="ui medium dividing header"><i class="save icon"></i> <?php esc_html_e( 'Quote Actions', 'zero-bs-crm' ); ?></div>

			<?php

			// localise ID & content
			$quoteID = -1;
			if ( is_array( $quote ) && isset( $quote['id'] ) ) {
				$quoteID = (int) $quote['id'];
			}

			#} if a saved post...
			// if (isset($post->post_status) && $post->post_status != "auto-draft"){
			if ( $quoteID > 0 ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
				?>
					<div class="zbs-quote-actions-bottom zbs-objedit-actions-bottom">

								<button class="ui button black" type="button" id="zbs-edit-save"><?php esc_html_e( 'Update', 'zero-bs-crm' ); ?> <?php esc_html_e( 'Quote', 'zero-bs-crm' ); ?></button>

						<?php

							// delete?

						// for now just check if can modify, later better, granular perms.
						if ( zeroBSCRM_permsQuotes() ) {
							?>
						<div id="zbs-quote-actions-delete" class="zbs-objedit-actions-delete">
							<a class="submitdelete deletion" href="<?php echo jpcrm_esc_link( 'delete', $quoteID, 'quote' ); ?>"><?php esc_html_e( 'Delete Permanently', 'zero-bs-crm' ); ?></a>
						</div>
						<?php } // can delete ?>
						
						<div class='clear'></div>

					</div>
				<?php

			} else {

				// NEW quote
				?>

						<button class="ui button black" type="button" id="zbs-edit-save"><?php esc_html_e( 'Save', 'zero-bs-crm' ); ?> <?php esc_html_e( 'Quote', 'zero-bs-crm' ); ?></button>

				<?php

			}

			?>
			</div>
			<?php
			// / .zbs-generic-save-wrap
	} // html

	// saved via main metabox
}

/*
======================================================
	/ Quotes Actions Metabox
	====================================================== */
