<?php
/*
  www.oscGold.com (C) Kamelia-Net Jacek Krysiak
  modul oscGold wer 4.0
*/


  class discount_coupon {

    var $messages, $coupon, $applied_discount, $cart_info;

    function discount_coupon( $code, $delivery ) {
      $this->messages = array();
      $this->coupon = array();
      $this->applied_discount = 0;
      $this->cart_info = array( 'valid_products' => array( 'count' => 0, 'line_items' => 0, 'total' => 0 ),
                                'total_products' => array( 'count' => 0, 'line_items' => 0, 'total' => 0 ),
                                'exclusions' => array() );
      $this->get_coupon( $code, $delivery );
    }

    function verify_code() {
      //if coupons_max_use==0, then use is unlimited, otherwise, we need to verify the customer hasn't used this coupon more than coupons_max_use times
      if( $this->coupon['coupons_max_use'] != 0 ) {
        $this->check_coupons_max_use();
      }	
      //check the global number of discounts that may be used
      if( $this->coupon['coupons_number_available'] != 0 ) {
        $this->check_num_available();
      }
    }

    function get_coupon( $code, $delivery ) {
      global $customer_id; //needed for customer_exclusions
      $check_code_query = tep_db_query( $sql = "SELECT dc.*
                                                FROM " . TABLE_DISCOUNT_COUPONS . " dc
                                                WHERE coupons_id = '".tep_db_input( $code )."'
                                                  AND ( coupons_date_start <= CURDATE() OR coupons_date_start IS NULL )
                                                  AND ( coupons_date_end >= CURDATE() OR coupons_date_end IS NULL )" );
      if( tep_db_num_rows( $check_code_query ) != 1 ) { //if no rows are returned, then they haven't entered a valid code
        $this->message( ENTRY_DISCOUNT_COUPON_ERROR ); //display the error message
      } else {
        //customer_exclusions
        $check_user_query = tep_db_query( $sql = 'SELECT dc2u.customers_id
                                                  FROM '.TABLE_DISCOUNT_COUPONS_TO_CUSTOMERS.' dc2u
                                                  WHERE customers_id='.$customer_id.'
                                                    AND coupons_id="'.tep_db_input( $code ).'"' );
        if( tep_db_num_rows( $check_user_query ) > 0 ) {
          $this->message( ENTRY_DISCOUNT_COUPON_ERROR ); //display the error message
          //use this to debug exclusions:
          //$this->message( 'Customer exclusion check failed' );
        }
        //shipping zone exclusions
        $check_user_query = tep_db_query($sql = 'SELECT dc2z.geo_zone_id
                                                  FROM '.TABLE_DISCOUNT_COUPONS_TO_ZONES.' dc2z
                                                  LEFT JOIN '.TABLE_ZONES_TO_GEO_ZONES.' z2g
                                                    USING( geo_zone_id )
                                                  WHERE ( z2g.zone_id='.$delivery['zone_id'].' or z2g.zone_id = 0 or z2g.zone_id IS NULL )
                                                    AND ( z2g.zone_country_id='.$delivery['country_id'].' or z2g.zone_country_id = 0 )
                                                    AND dc2z.coupons_id="'.tep_db_input( $code ).'"' );

          if (tep_db_num_rows( $check_user_query ) > 0 ) {
            $this->message( ENTRY_DISCOUNT_COUPON_ERROR ); //display the error message
          //use this to debug exclusions:
            //$this->message( 'Shipping Zones exclusion check failed' );
          }
          //end shipping zone exclusions
        $row = tep_db_fetch_array( $check_code_query ); //since there is one record, we have a valid code
        $this->coupon = $row;
      }
    }

    function check_coupons_min_order($wartosc_zamowienia) {
      switch( $this->coupon['coupons_min_order_type'] ) {
        //minimum number of products:
        case 'quantity':
          global $cart;
          //$total = $this->cart_info['valid_products']['count'];
		  $total = $wartosc_zamowienia;
          if( $this->coupon['coupons_min_order'] > $total ) { //make sure there are enough products in the cart
            $this->message( sprintf( ENTRY_DISCOUNT_COUPON_MIN_QUANTITY_ERROR, $this->coupon['coupons_min_order'] ) );
            return false;
          }
          break;
        //minimum price:
        case 'price':
        default:
          global $order, $currencies;
          //$total = $this->cart_info['valid_products']['total'];
		  $total = $wartosc_zamowienia;
          //if we display the subtotal without the discount applied, then just compare the subtotal to the minimum order
          if($this->coupon['coupons_min_order'] > $total ) {
            $this->message( sprintf( ENTRY_DISCOUNT_COUPON_MIN_PRICE_ERROR, $currencies->format( $this->coupon['coupons_min_order'], true, $order->info['currency'], $order->info['currency_value'] ) ).'.' );
            return false;
          }
          break;
      }
      return true;
    }

    function check_coupons_max_use() {
      global $customer_id;
      $check_use_query = tep_db_query($sql = "SELECT COUNT(*) AS cnt
                                              FROM ".TABLE_ORDERS." AS o
                                              INNER JOIN ".TABLE_DISCOUNT_COUPONS_TO_ORDERS." dc2o
                                                ON dc2o.orders_id=o.orders_id
                                                AND o.customers_id = '".(int)$customer_id."'
                                                AND dc2o.coupons_id='".tep_db_input( $this->coupon['coupons_id'] )."'");
      $use = tep_db_fetch_array( $check_use_query );
      //show error message if coupons_max_use is equal to the number of times this customer has used the code
      if( $this->coupon['coupons_max_use'] <= $use['cnt'] ) {
        $this->message( sprintf( ENTRY_DISCOUNT_COUPON_USE_ERROR, $use['cnt'], $this->coupon['coupons_max_use'] ) ); //display the error message for number of times used
        return false;
      }
      return true;
    }

    function check_num_available() {
      //count the number of times this coupon has been used
      $check_use_query = tep_db_query( $sql = 'SELECT COUNT(*) AS cnt
                                               FROM '.TABLE_DISCOUNT_COUPONS_TO_ORDERS.'
                                               WHERE coupons_id="'.tep_db_input( $this->coupon['coupons_id'] ).'"' );
      $use = tep_db_fetch_array( $check_use_query );
      if( $this->coupon['coupons_number_available'] <= $use['cnt'] ) {
        $this->message( ENTRY_DISCOUNT_COUPON_AVAILABLE_ERROR ); //display error that this coupon is no longer valid
        return false;
      }
      return true;
    }

    function is_recalc_shipping() {
      global $order, $language;

      //calculate the order total:
      $order_total = $order->info['total'] - $order->info['shipping_cost'];
      if( DISPLAY_PRICE_WITH_TAX != 'true' ) $order_total -= $order->info['tax'];
      //check if there is free shipping
      if( strtolower(MODULE_SHIPPING_FREEAMOUNT_STATUS) == 'true' ) {
        include( DIR_WS_LANGUAGES.$language.'/modules/shipping/kosztsprzedawcy.php' );
        // if free shipping is enabled, make sure the discount does not bring the order total below free shipping limit
        if( $order->info['shipping_method'] == MODULE_SHIPPING_FREEAMOUNT_TEXT_TITLE ) { //if free shipping is the selected shipping method
          if( $order_total < MODULE_SHIPPING_FREEAMOUNT_AMOUNT ) { //if the discount lowers the total below the free shipping limit
            return true;
          }
        }
      }

      //check if table rate shipping has changed
      if( strtolower(MODULE_SHIPPING_TABLE_STATUS) == 'true' ) {
        include( DIR_WS_LANGUAGES.$language.'/modules/shipping/table.php' );
        if( substr($order->info['shipping_method'], 0, strlen(MODULE_SHIPPING_TABLE_TEXT_TITLE)) == MODULE_SHIPPING_TABLE_TEXT_TITLE && MODULE_SHIPPING_TABLE_MODE == 'price' ) {
          $table_cost = split( "[:,]", MODULE_SHIPPING_TABLE_COST );
          for( $i = 0; $i < count( $table_cost ); $i += 2 ) {
            if( $order_total <= $table_cost[$i] ) {
              $shipping = $table_cost[$i+1];
              break;
            }
          }
          if( $order->info['shipping_cost'] != $shipping ) { //if the discount lowers the total below the table rate
            return true;
          }
        }
      }

      return false;
    }

    function is_allowed_product( $product_id ) {

      //category exclusion
      if( !is_array( $this->cart_info['exclusions']['categories'] ) ) { //only create the array when we need to and only once
        //check to see if the product is in one of the limited categories
        $check_category_query = tep_db_query( $sql = 'SELECT categories_id
                                                       FROM '.TABLE_DISCOUNT_COUPONS_TO_CATEGORIES.'
                                                       WHERE coupons_id="'.tep_db_input( $this->coupon['coupons_id'] ).'"' );
        $this->cart_info['exclusions']['categories'] = array();
        if( tep_db_num_rows( $check_category_query ) > 0 ) {
          //for each category, get all the child categories
          while( $categories = tep_db_fetch_array( $check_category_query ) ) {
            $this->cart_info['exclusions']['categories'][] = $categories['categories_id'];
            tep_get_subcategories( $this->cart_info['exclusions']['categories'], $categories['categories_id'] );
          }
          //$this->excluded_categories are all categories and subcategories excluded from use with the coupon code
          $this->cart_info['exclusions']['categories'] = array_unique( $this->cart_info['exclusions']['categories'] );
        }
      }
      if( count( $this->cart_info['exclusions']['categories'] ) > 0 ) {
        $c_path = tep_get_product_path( $product_id ); //get the product's cPath
        $this_products_catgeory_array = tep_parse_category_path( $c_path ); //convert the product's cPath into an array
        //if the product's cPath and the excluded categories array have elements in common, then the product is excluded
        $intersection = array_intersect( $this_products_catgeory_array, $this->cart_info['exclusions']['categories'] );
        if( is_array( $intersection ) && count( $intersection ) > 0 ) {
          return false;
        }
      }
      //end category exclusion

      //product exclusion
      if( !is_array( $this->cart_info['exclusions']['products'] ) ) { //only create the array when we need to and only once
        //check to see if the product is in one of the limited categories
        $check_product_query = tep_db_query( $sql = 'SELECT products_id
                                                     FROM '.TABLE_DISCOUNT_COUPONS_TO_PRODUCTS.'
                                                     WHERE coupons_id="'.tep_db_input( $this->coupon['coupons_id'] ).'"' );
        $this->cart_info['exclusions']['products'] = array();
        if( tep_db_num_rows( $check_product_query ) > 0 ) {
          while( $products = tep_db_fetch_array( $check_product_query ) ) {
            $this->cart_info['exclusions']['products'][] = $products['products_id'];
          }
        }
      }
      if( count( $this->cart_info['exclusions']['products'] ) > 0 ) {
        if( in_array( $product_id, $this->cart_info['exclusions']['products'] ) ) {
          return false;
        }
      }
      //end product exclusion

      //manufacturer exclusion
      if( !is_array( $this->cart_info['exclusions']['manufacturers'] ) ) { //only create the array when we need to and only once
        //check to see if the product is in one of the limited categories
        $check_manufacturer_query = tep_db_query( $sql = 'SELECT manufacturers_id
                                                           FROM '.TABLE_DISCOUNT_COUPONS_TO_MANUFACTURERS.'
                                                           WHERE coupons_id="'.tep_db_input( $this->coupon['coupons_id'] ).'"' );
        $this->cart_info['exclusions']['manufacturers'] = array();
        if( tep_db_num_rows( $check_manufacturer_query ) > 0 ) {
          while( $manufacturers = tep_db_fetch_array( $check_manufacturer_query ) ) {
            $this->cart_info['exclusions']['manufacturers'][] = $manufacturers['manufacturers_id'];
          }
        }
      }
      if( count( $this->cart_info['exclusions']['manufacturers'] ) > 0 ) {
        $check_manufacturer_query = tep_db_query( $sql = 'SELECT manufacturers_id
                                                           FROM '.TABLE_PRODUCTS.'
                                                           WHERE products_id="'.(int)$product_id.'"' );
        if( tep_db_num_rows( $check_manufacturer_query ) > 0 ) {
          $manufacturers = tep_db_fetch_array( $check_manufacturer_query );
          if( in_array( $manufacturers['manufacturers_id'], $this->cart_info['exclusions']['manufacturers'] ) ) {
            return false;
          }
        }
      }
      //end manufacturer exclusion

      //specials exclusion
      if( MODULE_ORDER_TOTAL_DISCOUNT_COUPON_EXCLUDE_SPECIALS == 'true' ) {
        if( ( $special_price = tep_get_products_special_price( $product_id ) ) !== null ) {
          $this->cart_info['exclusions']['products'][] = $product_id;
          return false;
        }
      }
      //end specials exclusion

      return true;
    }

    function is_exists_exclusions() {
      if( $this->cart_info['valid_products']['total'] != $this->cart_info['total_products']['total'] ) return true;
      if( $this->cart_info['valid_products']['count'] != $this->cart_info['total_products']['count'] ) return true;
      return false;
    }

    //this function is for tracking the product totals and count so that we can correctly calculate the discount
    function total_valid_products( $products = array() ) {
      global $cart;
      for( $i = 0; $i < count( $products ); $i++ ) {
        $price = ( $products[$i]['price'] + $cart->attributes_price( $products[$i]['id'] ) ) * $products[$i]['quantity'];
        $this->cart_info['total_products']['total'] += $price;
        $this->cart_info['total_products']['count'] += $products[$i]['quantity'];
        $this->cart_info['total_products']['line_items']++;
        if( $this->is_allowed_product( tep_get_prid( $products[$i]['id'] ) ) ) { //not an excluded product
          $this->cart_info['valid_products']['count'] += $products[$i]['quantity'];
          $this->cart_info['valid_products']['total'] += $price;
          $this->cart_info['valid_products']['line_items']++;
        }
      }
    }
    
    function czysc_cene($data) {
      global $currency,$currencies;
      
      $data = str_replace ($currencies->get_thousands_point($currency),'',$data);
      $data = str_replace ($currencies->get_decimal_point($currency),',',$data);
      //
      $data = preg_replace ('/[^0-9,]/', '', $data);
      $data = preg_replace ('/ /', '', $data);
      $data = preg_replace ('/,/', '.', $data);

      return $data;
    }    

    function calculate_discount() {
      global $cart,$currencies;
      $products = $cart->get_products();
      $promocjas = false;
      $wartosc_produktow = $cart->show_total();
      $wartosc_promocji = 0;
      //
      if( MODULE_ORDER_TOTAL_DISCOUNT_COUPON_EXCLUDE_SPECIALS == 'true' ) {
        for ($i=0, $n=sizeof($products); $i<$n; $i++) {    
            if( tep_get_products_special_price($products[$i]['id']) > 0 ) {
              $promocjas = true;
              $cena_promocyjna = $currencies->display_price_nodiscount($products[$i]['id'], $products[$i]['final_price'], tep_get_tax_rate($products[$i]['tax_class_id']), $products[$i]['quantity'],0, false);
              $cena_promocyjna = $this->czysc_cene($cena_promocyjna);
              $wartosc_promocji = $wartosc_promocji + $cena_promocyjna;
            }
          }      
      }

      if( $promocjas == true ) { //check that the product isn't excluded
        $wartosc_niepromocyjnych = $wartosc_produktow - $wartosc_promocji;        
        $wartosc_kuponu = $this->coupon['coupons_discount_amount'];
        if ($wartosc_niepromocyjnych < $wartosc_kuponu) {
            $applied_discount = $wartosc_niepromocyjnych;
          } else {
            $applied_discount = $this->coupon['coupons_discount_amount'];
        }
        //
        //$applied_discount = 0; //don't apply a discount
      } else {
        switch( $this->coupon['coupons_discount_type'] ) {
          case 'fixed':
            //get the percentage of the total discount to apply to this item:
            $applied_discount = $this->coupon['coupons_discount_amount'];
            break;
          case 'percent':
            //$applied_discount = $product['final_price'] * $this->coupon['coupons_discount_amount'] * $product['qty'];
			$applied_discount = $this->coupon['coupons_discount_amount'];
            break;
        }
      }

      //now determine how we need to handle tax:
      $discount_tax = 0;

      //tally the discount amount for each tax group
      $this->applied_discount = $applied_discount;

      $discount = array('applied_discount' => $applied_discount, 'discount_tax' => $discount_tax);
      return $discount;
    }

    function finalize_discount( $info, $products_tax ) {
      //make sure we meet the order minimum
      if( !$this->check_coupons_min_order($info['total']) ) {
          $this->applied_discount = 0;
      }
      if( $this->is_exists_exclusions() ) { 
          $this->applied_discount = 0;
          $this->message( ENTRY_DISCOUNT_COUPON_EXCLUSION_ERROR ); //add on to the min_order error message since we have excluded items
      }
      //}
      if( !$this->is_errors() ) { //if there are no errors, we can apply the discount
	    if ($this->coupon['coupons_discount_type'] == 'percent') {	
			//$info['total'] -= $info['total'] * $this->applied_discount;
			$info['total'] -= $info['subtotal'] * $this->applied_discount;
			//
			} else {
			$info['total'] -= $this->applied_discount;
		}
        if($info['total'] < 0 ) $info['total'] = 0;
      }
      return $info['total'];
    }

    function format_display() {
      global $order, $currencies;

      $display = ( MODULE_ORDER_TOTAL_DISCOUNT_COUPON_USE_LANGUAGE_FILE == 'true' ? MODULE_ORDER_TOTAL_DISCOUNT_COUPON_DISPLAY_FILE : MODULE_ORDER_TOTAL_DISCOUNT_COUPON_DISPLAY_CONFIG );

      switch( $this->coupon['coupons_discount_type'] ) {
        case 'percent':
          $discount_amount = ( $this->coupon['coupons_discount_amount'] * 100 ).'%';
          break;
        case 'fixed':
          $discount_amount = $currencies->format( $this->coupon['coupons_discount_amount'] );
          break;
      }

      $min_order = ( $this->coupon['coupons_min_order'] != 0 ? ( $this->coupon['coupons_min_order_type'] == 'price' ? $currencies->format( $this->coupon['coupons_min_order'] ) : (int)$this->coupon['coupons_min_order'] ) : '' );

      //replace the variables with their proper values:
      $display = str_replace( '[code]', $this->coupon['coupons_id'], $display );
      $display = str_replace( '[discount_amount]', $discount_amount, $display );
      $display = str_replace( '[coupon_desc]', $this->coupon['coupons_description'], $display );
      $display = str_replace( '[min_order]', $min_order, $display );
      $display = str_replace( '[number_available]', $this->coupon['coupons_number_available'], $display );
      return $display;
    }

    function is_errors() {
      if( count( $this->messages['error'] ) > 0 ) return true;
      return false;
    }

    function message( $message, $error_level = 'error' ) {
      $this->messages[$error_level][] = $message;
    }

    function get_messages( $error_level = 'error' ) {
      if( $error_level == 'debug' ) return $this->messages;
      return $this->messages[$error_level];
    }

  }
?>