<?php
/*+**********************************************************************************
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * The Original Code is:  vtiger CRM Open Source
 * The Initial Developer of the Original Code is vtiger.
 * Portions created by vtiger are Copyright (C) vtiger.
 * All Rights Reserved.
 ************************************************************************************/

require_once('include/utils/utils.php');
require_once 'include/utils/CommonUtils.php';

Class ChartUtils {

	// Function to generate Bar Chart
	public static function getBarChart($xaxisData, $yaxisData, $title='', $width='', $height='', $charttype='vertical', $cachedFileName=false, $target=false, $color='') {

		global $log, $lang_crm, $default_charset;

		require_once('include/utils/utils.php');
		require_once('include/utils/GraphUtils.php');
		include_once ('Image/Graph.php');
		include_once ('Image/Canvas.php');

		$barwidth = '70';
		if ($cachedFileName === false) {
			$cache_file_name = 'cache/images/bar_chart_' . time() . '.png';
		} else {
			$cache_file_name = $cachedFileName;
		}
		if (empty($width))
			$width = '400';
		if (empty($height))
			$height = '300';
		if ($target === false)
			$target = array();
		if (empty($color))
			$color = 'black';

		$alts = array();
		$temp = array();
		for ($i = 0; $i < count($xaxisData); $i++) {
			$name = html_entity_decode($xaxisData[$i], ENT_QUOTES, $default_charset);
			$pos = substr_count($name, " ");
			$alts[] = $name;
			//If the daatx value of a string is greater, adding '\n' to it so that it'll cme inh 2nd line
			if (strlen($name) >= 14)
				$name = substr($name, 0, 44);
			if ($pos >= 2) {
				$val = explode(" ", $name);
				$n = count($val) - 1;
				$x = "";
				for ($j = 0; $j < count($val); $j++) {
					if ($j != $n) {
						$x .=" " . $val[$j];
					} else {
						$x .= "@#" . $val[$j];
					}
				}
				$name = $x;
			}
			$name = str_replace("@#", " ", $name);
			$temp[] = html_entity_decode($name, ENT_QUOTES, $default_charset);
		}
		$xaxisData = $temp;

		// Set the basic parameters of the graph
		$canvas = & Image_Canvas::factory('png', array('width' => $width, 'height' => $height, 'usemap' => true));
		$imagemap = $canvas->getImageMap();
		$graph = & Image_Graph::factory('graph', $canvas);

		$font = & $graph->addNew('font', calculate_font_name($lang_crm));
		$font->setSize(8);
		$font_color = "#000000";
		$font->setColor($font_color);
		$graph->setFont($font);

		$titlestr = & Image_Graph::factory('title', array($title, 8));
		$plotarea = & Image_Graph::factory('plotarea', array(
					'axis',
					'axis',
					$charttype
				));
		$graph->add(Image_Graph::vertical($titlestr, $plotarea, 5));

		// Now create a bar plot
		$max = 0;
		// To create unique lables we need to keep track of lable name and its count
		$uniquex = array();

		$xlabels = array();
		$dataset = & Image_Graph::factory('dataset');
		if ($charttype == 'horizontal') {
			$fill = & Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED, $color, 'white'));
		} else {
			$fill = & Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED, $color, 'white'));
		}

		for ($i = 0; $i < count($yaxisData); $i++) {
			$x = 1 + $i;
			if ($yaxisData[$i] >= $max)
				$max = $yaxisData[$i];
			$dataset->addPoint(
					$x,
					$yaxisData[$i],
					array(
						'url' => $target[$i],
						'alt' => $alts[$i] . '=' . $yaxisData[$i]
					)
			);
			$xlabels[$x] = $xaxisData[$i];

			// To have unique names even in case of duplicates let us add the id
			$xaxisData_appearance = $uniquex[$xaxisData[$i]];
			if ($xaxisData_appearance == null) {
				$uniquex[$xaxisData[$i]] = 1;
			} else {
				$xlabels[$x] = $xaxisData[$i] . ' [' . $xaxisData_appearance . ']';
				$uniquex[$xaxisData[$i]] = $xaxisData_appearance + 1;
			}
		}
		$bplot = & $plotarea->addNew('bar', $dataset);
		$bplot->setFillStyle($fill);

		//You can change the width of the bars if you like
		if (!empty($xaxisData))
			$bplot->setBarWidth($barwidth / count($xaxisData), "%");
		//$bplot->setPadding(array('top'=>10));
		$bplot->setBackground(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL, 'white', 'white')));
		$xaxis = & $plotarea->getAxis(IMAGE_GRAPH_AXIS_X);
		$yaxis = & $plotarea->getAxis(IMAGE_GRAPH_AXIS_Y);
		$yaxis->setFontSize(8);
		$xaxis->setFontSize(8);

		if ($charttype == 'horizontal') { // Invert X-axis and put Y-axis at bottom
			$xaxis->setInverted(false);
			$yaxis->setAxisIntersection('max');
		}

		// set grid
		$gridY = & $plotarea->addNew('line_grid', IMAGE_GRAPH_AXIS_Y);
		$gridY->setLineColor('#FFFFFF@0.5');
		$gridY2 = & $plotarea->addNew('bar_grid', null, IMAGE_GRAPH_AXIS_Y);
		$gridY2->setFillColor('#FFFFFF@0.2');


		// Add some grace to y-axis so the bars doesn't go all the way to the end of the plot area
		$yaxis->forceMaximum(round(($max * 1.1) + 0.5));
		$ticks = get_tickspacing(round(($max * 1.1) + 0.5));

		// First make the labels look right
		if ($charttype == 'horizontal')
			$yaxis->setFontAngle('vertical');
		$yaxis->setLabelInterval($ticks[0]);
		$yaxis->setTickOptions(-5, 0);
		$yaxis->setLabelInterval($ticks[1], 2);
		$yaxis->setTickOptions(-2, 0, 2);

		// Create the xaxis labels
		$array_data = & Image_Graph::factory('Image_Graph_DataPreprocessor_Array',
						array($xlabels)
		);

		// The fix the tick marks
		$xaxis->setDataPreprocessor($array_data);
		$xaxis->forceMinimum(0.5);
		$xaxis->forceMaximum(0.5 + count($yaxisData));
		if ($charttype == 'vertical')
			$xaxis->setFontAngle('vertical');
		$xaxis->setLabelInterval(1);
		$xaxis->setTickOptions(0, 0);
		$xaxis->setLabelInterval(2, 2);

		// set markers
		if ($width > 400 && $height > 400) {
			$marker = & $graph->addNew('value_marker', IMAGE_GRAPH_VALUE_Y);
			$marker->setFillColor('000000@0.0');
			$marker->setBorderColor('000000@0.0');
			$marker->setFontSize(8);
			// shift markers 20 pix right
			if ($charttype == 'horizontal') {
				$marker_pointing = & $graph->addNew('Image_Graph_Marker_Pointing', array(10, 0, & $marker));
			} else {
				$marker_pointing = & $graph->addNew('Image_Graph_Marker_Pointing', array(0, -10, & $marker));
			}
			$marker_pointing->setLineColor('000000@0.0');
			$bplot->setMarker($marker_pointing);
		}

		//Getting the graph in the form of html page
		$img = $graph->done(
						array(
							'tohtml' => true,
							'border' => 0,
							'filename' => $cache_file_name,
							'filepath' => '',
							'urlpath' => ''
				));

		return $img;
	}

	// Function to generate Pie Chart
	public static function getPieChart($xaxisData, $yaxisData, $title='', $width='', $height='', $charttype='vertical', $cachedFileName=false, $target=false, $color='') {

		global $log, $lang_crm, $default_charset;

		require_once('include/utils/utils.php');
		require_once('include/utils/GraphUtils.php');
		include_once ('Image/Graph.php');
		include_once ('Image/Canvas.php');

		if ($cachedFileName === false) {
			$cache_file_name = 'cache/images/pie_chart_' . time() . '.png';
		} else {
			$cache_file_name = $cachedFileName;
		}

		if (empty($width))
			$width = '500';
		if (empty($height))
			$height = '400';
		if ($target === false)
			$target = array();

		$alts = array();
		$temp = array();
		for ($i = 0; $i < count($xaxisData); $i++) {
			$name = html_entity_decode($xaxisData[$i], ENT_QUOTES, $default_charset);
			$pos = substr_count($name, " ");
			$alts[] = $name;
			//If the datax value of a string is greater, adding '\n' to it so that it'll come in 2nd line
			if (strlen($name) >= 14)
				$name = substr($name, 0, 34);
			if ($pos >= 2) {
				$val = explode(" ", $name);
				$n = count($val) - 1;
				$x = "";
				for ($j = 0; $j < count($val); $j++) {
					if ($j != $n) {
						$x .=" " . $val[$j];
					} else {
						$x .= "@#" . $val[$j];
					}
				}
				$name = $x;
			}
			$name = str_replace("@#", "\n", $name);
			$temp[] = $name;
		}
		$xaxisData = $temp;
		$width = $width + ($width / 5);

		$canvas = & Image_Canvas::factory('png', array('width' => $width, 'height' => $height, 'usemap' => true));
		$imagemap = $canvas->getImageMap();
		$graph = & Image_Graph::factory('graph', $canvas);
		$font = & $graph->addNew('font', calculate_font_name($lang_crm));
		$font->setSize(8);
		$font->setColor($color);
		$graph->setFont($font);
		// create the plotarea layout
		$title = & Image_Graph::factory('title', array($title, 10));
		$plotarea = & Image_Graph::factory('plotarea', array(
					'category',
					'axis'
				));
		$graph->add(Image_Graph::vertical($title, $plotarea, 5));
		// To create unique lables we need to keep track of lable name and its count
		$uniquex = array();
		// Generate colours
		$colors = color_generator(count($yaxisData), '#33DDFF', '#3322FF');
		$dataset = & Image_Graph::factory('dataset');
		$fills = & Image_Graph::factory('Image_Graph_Fill_Array');
		$sum = 0;
		$pcvalues = array();
		for ($i = 0; $i < count($yaxisData); $i++) {
			$sum += $yaxisData[$i];
		}
		for ($i = 0; $i < count($yaxisData); $i++) {
			// To have unique names even in case of duplicates let us add the id
			$datalabel = $xaxisData[$i];
			$xaxisData_appearance = $uniquex[$xaxisData[$i]];
			if ($xaxisData_appearance == null) {
				$uniquex[$xaxisData[$i]] = 1;
			} else {
				$datalabel = $xaxisData[$i] . ' [' . $xaxisData_appearance . ']';
				$uniquex[$xaxisData[$i]] = $xaxisData_appearance + 1;
			}
			$dataset->addPoint(
					$datalabel,
					$yaxisData[$i],
					array(
						'url' => $target[$i],
						'alt' => $alts[$i] . '=' . sprintf('%0.1f%%', 100 * $yaxisData[$i] / $sum)
					)
			);
			$pcvalues[$yaxisData[$i]] = sprintf('%0.1f%%', 100 * $yaxisData[$i] / $sum);
			$fills->addColor($colors[$i]);
		}
		if ($sum == 0)
			return null;
		// create the pie chart and associate the filling colours
		$gbplot = & $plotarea->addNew('pie', $dataset);
		$plotarea->setPadding(array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => ($width / 20)));
		$plotarea->hideAxis();
		$gbplot->setFillStyle($fills);
		// format the data values
		$marker_array = & Image_Graph::factory('Image_Graph_DataPreprocessor_Array', array($pcvalues));
		// set markers
		$marker = & $graph->addNew('value_marker', IMAGE_GRAPH_VALUE_Y);
		$marker->setDataPreprocessor($marker_array);
		$marker->setFillColor('#FFFFFF');
		$marker->setBorderColor($color);
		$marker->setFontColor($color);
		$marker->setFontSize(8);
		$pointingMarker = & $graph->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$marker));
		$gbplot->setMarker($pointingMarker);
		$legend_box = & $plotarea->addNew('legend');
		$legend_box->setPadding(array('top' => 20, 'bottom' => 0, 'left' => 0, 'right' => 0));
		$legend_box->setFillColor('#F5F5F5');
		$legend_box->showShadow();

		$img = $graph->done(array(
					'tohtml' => true,
					'border' => 0,
					'filename' => $cache_file_name,
					'filepath' => '',
					'urlpath' => ''
				));
		return $img;
	}

	//Generates Chart Data in form of an array from the Query Result of reports
	public static function generateChartDataFromReports($queryResult, $groupbyField, $fieldDetails='', $reportid='') {
		require_once 'modules/Reports/CustomReportUtils.php';
		require_once('include/Webservices/Utils.php');
		require_once('include/Webservices/Query.php');
		global $adb, $current_user, $theme, $default_charset;
		$inventorymodules = array('Quotes', 'SalesOrder', 'PurchaseOrder', 'Invoice', 'Products', 'PriceBooks', 'Vendors', 'Services');
		$rows = $adb->num_rows($queryResult);
		$condition = "is";
		$current_theme = $theme;
		$groupByFields = array();
		$yaxisArray = array();
		$ChartDataArray = array();
		$target_val = array();

		$report = new ReportRun($reportid);
		$restrictedModules = array();
		if($report->secondarymodule!='') {
			$reportModules = explode(":",$report->secondarymodule);
		} else {
			$reportModules = array();
		}
		array_push($reportModules,$report->primarymodule);

		$restrictedModules = false;
		foreach($reportModules as $mod) {
			if(isPermitted($mod,'index') != "yes" || vtlib_isModuleActive($mod) == false) {
				if(!is_array($restrictedModules)) $restrictedModules = array();
				$restrictedModules[] = $mod;
			}
		}

		if(is_array($restrictedModules) && count($restrictedModules) > 0) {
			$ChartDataArray['error'] = "<h4>".getTranslatedString('LBL_NO_ACCESS', 'Reports').' - '.implode(',', $restrictedModules)."</h4>";
			return $ChartDataArray;
		}

		if ($fieldDetails != '') {
			list($tablename, $colname, $module_field, $fieldname, $single) = explode(":", $fieldDetails);
			list($module, $field) = split("_", $module_field);
			$dateField = false;
			if ($single == 'D') {
				$dateField = true;
				$query = "SELECT * FROM vtiger_reportgroupbycolumn WHERE reportid=? ORDER BY sortid";
				$result = $adb->pquery($query, array($reportid));
				$criteria = $adb->query_result($result, 0, 'dategroupbycriteria');
			}
		}
		preg_match('/&amp;/', $groupbyField, $matches);
		if (!empty($matches)) {
			$groupfield = str_replace('&amp;', '&', $groupbyField);
			$groupbyField = $report->replaceSpecialChar($groupfield);
		}
		$handler = vtws_getModuleHandlerFromName($module, $current_user);
		$meta = $handler->getMeta();
		$meta->retrieveMeta();
		$referenceFields = $meta->getReferenceFieldDetails();

		if($rows > 0) {
			$resultRow = $adb->query_result_rowdata($queryResult, 0);
			if(!array_key_exists($groupbyField, $resultRow)) {
				$ChartDataArray['error'] = "<h4>".getTranslatedString('LBL_NO_PERMISSION_FIELD', 'Dashboard')."</h4>";
				return $ChartDataArray;
			}
		}
		for ($i = 0; $i < $rows; $i++) {
			$groupFieldValue = $adb->query_result($queryResult, $i, strtolower($groupbyField));
			$decodedGroupFieldValue = html_entity_decode($groupFieldValue, ENT_QUOTES, $default_charset);
			if (!empty($groupFieldValue)) {
				if (in_array($module_field, $report->append_currency_symbol_to_value)) {
					$valueComp = explode('::', $groupFieldValue);
					$groupFieldValue = $valueComp[1];
				}
				if ($dateField) {
					if (!empty($groupFieldValue))
						$groupByFields[] = CustomReportUtils::getXAxisDateFieldValue($groupFieldValue, $criteria);
					else
						$groupByFields[] = "Null";
				}
				else if (in_array($fieldname, array_keys($referenceFields))) {
					if (count($referenceFields[$fieldname]) > 1) {
						$refenceModule = CustomReportUtils::getEntityTypeFromName($decodedGroupFieldValue, $referenceFields[$fieldname]);
					}
					else {
						$refenceModule = $referenceFields[$fieldname][0];
					}
					$groupByFields[] = $groupFieldValue;

					if ($fieldname == 'currency_id' && in_array($module, $inventorymodules)) {
						$tablename = 'vtiger_currency_info';
					} elseif ($refenceModule == 'DocumentFolders' && $fieldname == 'folderid') {
						$tablename = 'vtiger_attachmentsfolder';
						$colname = 'foldername';
					} else {
						require_once "modules/$refenceModule/$refenceModule.php";
						$focus = new $refenceModule();
						$tablename = $focus->table_name;
						$colname = $focus->list_link_field;
						$condition = "c";
					}
				} else {
					$groupByFields[] = $groupFieldValue;
				}
				$yaxisArray[] = $adb->query_result($queryResult, $i, 'groupby_count');
				if ($fieldDetails != '') {
					if ($dateField) {
						$advanceSearchCondition = CustomReportUtils::getAdvanceSearchCondition($fieldDetails, $criteria, $groupFieldValue);
						if ($module == 'Calendar') {
							$link_val = "index.php?module=" . $module . "&query=true&action=ListView&" . $advanceSearchCondition;
						}else
							$link_val = "index.php?module=" . $module . "&query=true&action=index&" . $advanceSearchCondition;
					}
					else {
						$cvid = getCvIdOfAll($module);
						$esc_search_str = urlencode($decodedGroupFieldValue);
						if ($single == 'DT') {
							$esc_search_str = urlencode($groupFieldValue);
							if (strtolower($fieldname) == 'modifiedtime' || strtolower($fieldname) == 'createdtime') {
								$tablename = 'vtiger_crmentity';
								$colname = $fieldname;
							}
						}
						if ($fieldname == 'assigned_user_id') {
							$tablename = 'vtiger_crmentity';
							$colname = 'smownerid';
						}

						if ($module == 'Calendar') {
							$link_val = "index.php?module=" . $module . "&action=ListView&search_text=" . $esc_search_str . "&search_field=" . $fieldname . "&searchtype=BasicSearch&query=true&operator=e&viewname=" . $cvid;
						} else {
							$link_val = "index.php?module=" . $module . "&action=index&search_text=" . $esc_search_str . "&search_field=" . $fieldname . "&searchtype=BasicSearch&query=true&operator=e&viewname=" . $cvid;
						}
					}

					$target_val[] = $link_val;
				}
			}
		}
		if(count($groupByFields) == 0) {
			$ChartDataArray['error'] = "<div class='componentName'>".getTranslatedString('LBL_NO_DATA', 'Reports')."</div";
		}
		$ChartDataArray['xaxisData'] = $groupByFields;
		$ChartDataArray['yaxisData'] = $yaxisArray;
		$ChartDataArray['targetLink'] = $target_val;
		$theme = $current_theme;
		return $ChartDataArray;
	}

	public static function getReportBarChart($queryResult, $groupbyField, $fieldDetails, $reportid, $charttype='horizontal') {
		global $theme;
		$BarChartDetails = self::generateChartDataFromReports($queryResult, $groupbyField, $fieldDetails, $reportid);
		$groupbyFields = $BarChartDetails['xaxisData'];
		$yaxisArray = $BarChartDetails['yaxisData'];
		$targerLinks = $BarChartDetails['targetLink'];
		if ($theme == "softed") {
			$font_color = "#212473";
		} else {
			$font_color = "#000000";
		}
		if(!empty($BarChartDetails['error'])) {
			return $BarChartDetails['error'];
		} else {
			$barChart = ChartUtils::getBarChart($groupbyFields, $yaxisArray, '', '350', '300', $charttype, false, $targerLinks, $font_color);
			return $barChart;
		}
	}

	public static function getReportPieChart($queryResult, $groupbyField, $fieldDetails, $reportid) {
		global $theme;
		$PieChartDetails = self::generateChartDataFromReports($queryResult, $groupbyField, $fieldDetails, $reportid);
		$groupbyFields = $PieChartDetails['xaxisData'];
		$yaxisArray = $PieChartDetails['yaxisData'];
		$targerLinks = $PieChartDetails['targetLink'];
		$charttype = 'vertical';
		if ($theme == "softed") {
			$font_color = "#212473";
		} else {
			$font_color = "#000000";
		}
		if(!empty($PieChartDetails['error'])) {
			return $PieChartDetails['error'];
		} else {
			$pieChart = ChartUtils::getPieChart($groupbyFields, $yaxisArray, '', '350', '300', $charttype, false, $targerLinks, $font_color);
			return $pieChart;
		}
	}

}

?>
