/**
     * Output origin address select metabox
     *
     * @since 4.2
     * @param (WP_Post) $post post/product being edited
     */
    public static function output_shipping_metabox($post)
    {
        $addresses = fetch_business_addresses();
        echo '<p>Use the box below to search for and add "Shipping Origin Addresses" for this product. These are the locations from which this
		item will be shipped.</p>';
        echo '<p>When an item can be shipped from multiple locations, WooTax will assume that it is sent from the business location in the customer\'s state.</p>';
        // Fetch addresses for this product
        $origin_addresses = fetch_product_origin_addresses($post->ID);
        // Output addresses
        echo '<select class="' . (version_compare(WOOCOMMERCE_VERSION, '2.3', '<') ? 'chosen_select' : 'wc-enhanced-select') . '" name="_wootax_origin_addresses[]" multiple>';
        if (is_array($addresses) && count($addresses) > 0) {
            foreach ($addresses as $key => $address) {
                echo '<option value="' . $key . '"' . (in_array($key, $origin_addresses) ? " selected" : "") . '>' . get_formatted_address($address) . '</option>';
            }
        } else {
            echo '<option value="">There are no addresses to select.</option>';
        }
        echo '</select>';
    }
 /**
  * Stores an array of items in TaxCloud-friendly format and organized by location key in the lookup_data property
  *
  * @since 4.2
  */
 private function generate_lookup_data($items = NULL)
 {
     // Fetch order items
     $order_items = $items;
     // Exit if we do not have any items
     if (count($order_items) == 0) {
         WT_Orders::update_meta($this->order_id, 'lookup_data', array());
         WT_Orders::update_meta($this->order_id, 'mapping_array', array());
         return;
     }
     // Determine the state where the customer is located
     $customer_state = $this->destination_address['State'];
     // Initialize some vars that we need for the foreach loop below
     $data = $mapping_array = $counters_array = $fee_items = $shipping_items = array();
     // This will hold the ID of the first found origin address/location for this order; Fees and shipping chars will be attached to it
     $first_found = false;
     // Loop through order items; group items by their shipping origin address and format data for tax lookup
     foreach ($order_items as $item_key => $item) {
         $item_id = $item['ItemID'];
         $type = $item['Type'];
         switch ($type) {
             case 'cart':
                 // Fetch shipping origin addresses for this product_id
                 $item_ids = array('product_id' => $this->order->get_item_meta($item_id, '_product_id', true), 'variation_id' => $this->order->get_item_meta($item_id, '_variation_id', true));
                 $product = $this->order->get_product_from_item($item_ids);
                 $origin_addresses = fetch_product_origin_addresses($product->id);
                 $address_found = WT_DEFAULT_ADDRESS;
                 /**
                  * Attempt to find proper origin address
                  * If there is more than one address available, we will use the first address that occurs in the customer's state 
                  * If there no shipping location in the customer's state, we will use the default origin address
                  * Developers can modify the selected shipping origin address using the wootax_origin_address filter
                  */
                 if (count($origin_addresses) == 1) {
                     // There is only one address ID to fetch, with index 0
                     $address_found = $origin_addresses[0];
                 } else {
                     // Find an address in the customer's state if possible
                     foreach ($origin_addresses as $key) {
                         if (isset(WT_Orders::$addresses[$key]['state']) && WT_Orders::$addresses[$key]['state'] == $customer_state) {
                             $address_found = $key;
                             break;
                         }
                     }
                 }
                 // Allow developers to use their own logic to determine the appropriate shipment origin for a product
                 $address_found = apply_filters('wootax_origin_address', $address_found, $customer_state, $this);
                 // Store the id of the first shipping location we find for the order so we can attach shipping items and fees later on
                 if ($first_found === false) {
                     $first_found = $address_found;
                 }
                 // Initialize arrays to avoid PHP notices
                 if (!isset($data[$address_found]) || !is_array($data[$address_found])) {
                     $data[$address_found] = array();
                 }
                 if (!isset($counters_array[$address_found])) {
                     $counters_array[$address_found] = 0;
                 }
                 if (!isset($mapping_array[$address_found])) {
                     $mapping_array[$address_found] = array();
                 }
                 // Update mapping array
                 $mapping_array[$address_found][] = $item_id;
                 // Update item data before storing in $data array
                 $item['Index'] = $counters_array[$address_found];
                 $item['Price'] = apply_filters('wootax_taxable_price', $item['Price'], false, $item_id);
                 unset($item['Type']);
                 // Add formatted item data to the $data array
                 $data[$address_found][] = $item;
                 // Increment counter
                 $counters_array[$address_found]++;
                 break;
             case 'shipping':
                 // Push this item to the shipping array; the cost of shipping will be attached to the first daughter order later on
                 $shipping_items[$item_id] = $item;
                 break;
             case 'fee':
                 // Push this item to the fee array; it will be attached to the first daughter order later on
                 $fee_items[$item_id] = $item;
                 break;
         }
     }
     // Attach shipping items and fees to the first daughter order
     if ($first_found !== false) {
         foreach ($shipping_items + $fee_items as $key => $item) {
             // Get new item index
             $index = $counters_array[$first_found];
             // Add to items array (Type index not included here)
             $data[$first_found][] = array('Index' => $index, 'ItemID' => $item['ItemID'], 'TIC' => $item['TIC'], 'Price' => apply_filters('wootax_taxable_price', $item['Price'], false, $item['ItemID']), 'Qty' => $item['Qty']);
             // Update mapping array
             $mapping_array[$first_found][$index] = $key;
             // Increment counter
             $counters_array[$first_found]++;
         }
     }
     // Save mapping array/first found and return lookup data
     WT_Orders::update_meta($this->order_id, 'mapping_array', $mapping_array);
     WT_Orders::update_meta($this->order_id, 'first_found', $first_found);
     return $data;
 }