<?php
class ReportPage extends RunnerPage
{

	public $pagestart = 0;

	public $arrReport = array();

	/**
	 * Array of groups per page for report with group fields
	 * @var array
	 * @intellisense
	 */
	public $arrGroupsPerPage = array();

	/**
	 * The flag indicating that report is cross-table
	 */
	public $crossTable = false;

	/**
	 * Refresh the crosstab report
	 */
	public $crosstableRefresh = false;

	/**
	 * @type Boolean
	 */
	protected $noRecordsFound = false;

	protected $crossTableObj = null;

	public $pdfJson = false;

	public $x;
	public $y;
	public $dataField;
	public $operation;
	public $xType;
	public $yType;
	public $selectedAxis;
	public $requestGoto;
	/**
	 * @constructor
	 * @param &Array params
	 */
	function __construct( &$params )
	{
		parent::__construct($params);

		$this->crossTable = $this->pSet->isCrossTabReport();

		$this->jsSettings['tableSettings'][ $this->tName ]['crossTable'] = $this->crossTable;
		$this->jsSettings['tableSettings'][ $this->tName ]['simpleSearchActive'] = $this->searchClauseObj->simpleSearchActive;

		if( $this->mode == REPORT_DASHBOARD || $this->mode == REPORT_DETAILS || $this->mode == REPORT_DASHDETAILS )
		{
			if( $this->mode != REPORT_DETAILS )
			{
				$this->formBricks["header"] = array(
					array( "name" => "details_found", "align" => "right" )
				);
			}
			$this->formBricks["footer"] = array( "pagination_block" );
		}

		$this->controlsMap["pdfSettings"] = array();
		$this->controlsMap["pdfSettings"]["allPagesMode"] = 0;
	}

	/**
	 * Set the page's session prefix
	 */
	protected function assignSessionPrefix()
	{
		if( $this->mode == REPORT_DASHBOARD )
			$this->sessionPrefix = $this->dashTName."_".$this->tName;
		else
			$this->sessionPrefix = $this->tName;
	}

	/**
	 * Set session variables
	 */
	public function setSessionVariables()
	{
		parent::setSessionVariables();

		$_SESSION[$this->sessionPrefix.'_advsearch'] = serialize($this->searchClauseObj);

		if( !$_SESSION[$this->sessionPrefix."_pagesize"] )
			$_SESSION[$this->sessionPrefix."_pagesize"] = $this->pSet->getInitialPageSize();

		$this->pageSize = $_SESSION[$this->sessionPrefix."_pagesize"];

		if( !$_SESSION[ $this->sessionPrefix."_pagenumber" ] )
			$_SESSION[ $this->sessionPrefix."_pagenumber" ] = 1;

		if( $this->requestGoto )
			$_SESSION[ $this->sessionPrefix."_pagenumber" ] = $this->requestGoto;

		$this->myPage = $_SESSION[$this->sessionPrefix."_pagenumber"];

		$this->pagestart = ($this->myPage - 1) * $this->pageSize;
		if( $this->pageSize < 0 ) {
			$this->pagestart = 0;
		}
	}


	/**
	 * Process the page
	 */
	public function process()
	{
		if( $this->mode == REPORT_DASHDETAILS
			|| $this->mode == REPORT_DETAILS && ( $this->masterPageType == PAGE_LIST || $this->masterPageType == PAGE_REPORT ))
			$this->updateDetailsTabTitles();

		if( $this->crossTable && !$this->checkCrossParams() )
		{
			if( $this->mode == REPORT_SIMPLE )
			{
				$this->crossTableBaseRedirect();
				return;
			}

			$this->setDefaultParams();
		}

		//	Before Process event
		if( $this->eventsObject->exists("BeforeProcessReport") )
			$this->eventsObject->BeforeProcessReport( $this );

		$this->setDetailsBadgeStyles();
		// array with extra report params
		$extraParams = $this->getExtraReportParams();

		$this->setGoogleMapsParams( $extraParams['fieldsArr'] );
		$this->fillAdvancedMapData();
		if( $this->googleMapCfg['isUseGoogleMap'] )
			$this->initGmaps();

		if( $this->mode != REPORT_DASHBOARD ) {
			$this->buildSearchPanel();
			$this->assignSimpleSearch();
		}

		// build tabs and set current
		$this->processGridTabs();

		RunnerContext::pushSearchContext( $this->searchClauseObj );

		$this->setReportData( $extraParams );

		$this->addCommonJs();
		$this->addButtonHandlers();
		$this->commonAssign();
		$this->doCommonAssignments();
		$this->addCustomCss();

		// display the 'Back to Master' link and master table info
		if( $this->mode == REPORT_SIMPLE )
			$this->displayMasterTableInfo();

		$this->showPage();
	}

	/**
	 * @return Boolean
	 */
	protected function checkCrossParams()
	{
		if( !$this->crossTable )
			return true;

		return strlen( $this->x ) && strlen( $this->y ) && strlen( $this->dataField );
	}

	/**
	 *
	 */
	protected function setDefaultParams()
	{
		$prms = $this->getDefaultCrossParams();

		$this->x = $prms["x"];
		$this->y = $prms["y"];
		$this->dataField = $prms["data"];
		$this->operation = $prms["op"];
	}

	/**
	 * Fix it!
	 * @return Array
	 */
	protected function getDefaultCrossParams()
	{
		if( !$this->crossTable )
			return array();

		$xNames = array();
		$yNames = array();
		$allNames = array();
		foreach( $this->pSet->getReportGroupFieldsData() as $ind => $value )
		{
			$axisName = $value["strGroupField"];

			if( $value["crossTabAxis"] == 0 )
				$xNames[] = $axisName;
			elseif( $value["crossTabAxis"] == 1 )
				$yNames[] = $axisName;
			else
				$allNames[]= $axisName;
		}

		if( $xNames )
			$x = $xNames[0];
		else
			$x = $allNames[0];

		if( $yNames )
			$y = $yNames[0];
		else
		{
			if( !$xNames )
				$y = $allNames[1];
			else
				$y = $allNames[0];
		}

		$dataField = "";
		$operation = "";
		$reportFields = $this->pSet->getFieldsList();
		foreach( $reportFields as $field )
		{
			$operation = "";
			$fieldInfo = $this->pSet->reportFieldInfo( $field );
			if( $fieldInfo ) {
				if( $fieldInfo["max"] )
					$operation = "max";
				else if( $fieldInfo["min"] )
					$operation = "min";
				else if( $fieldInfo["avg"] )
					$operation = "avg";
				else if( $fieldInfo["sum"] )
					$operation = "sum";
			}
			if( $operation )
			{
				$dataField = $field;
				break;
			}
		}

		return array( "x" => $x, "y" => $y, "data" => $dataField, "op" => $operation );
	}

	/**
	 * @return Array
	 */
	protected function getCurrentCrossParams()
	{
		$prms = array( "x" => $this->x, "y" => $this->y, "data" => $this->dataField, "op" => $this->operation );

		if( $this->xType )
			$prms["xtype"] = $this->xType;

		if( $this->yType )
			$prms["ytype"] = $this->yType;

		return $prms;
	}

	/**
	 * @return String
	 */
	protected function getDefaultCrossParamsString()
	{
		$prms = $this->getDefaultCrossParams();
		return "x=".$prms["x"]."&y=".$prms["y"]."&data=".$prms["data"]."&op=".$prms["op"];
	}

	/**
	 *
	 */
	protected function crossTableBaseRedirect()
	{
		HeaderRedirect( $this->pSet->getShortTableName(), $this->getPageType(),
			implode( '&', array( $this->getDefaultCrossParamsString(), $this->getStateUrlParams() ) ) );
		exit();
	}

	/**
	 * Get the report data, assign corresponding xt variables
	 * @param Array options
	 */
	public function setReportData( $options )
	{
		if( $this->crossTable )
			$this->setCrosstabData( $options );
		else
			$this->setStandartData( $options );
	}

	/**
	 *
	 */
	protected function getCrossGroupFieldsSettings( $repGroupFields )
	{
		$groupFields = array();

		$xNames = array();
		$yNames = array();

		$xFieldsCount = array();
		$yFieldsCount = array();

		foreach( $repGroupFields as $ind => $value )
		{
			if( $value["crossTabAxis"] == 0 || $value["crossTabAxis"] == 2 )
				++$xFieldsCount[ $value["strGroupField"] ];
			if( $value["crossTabAxis"] == 1 || $value["crossTabAxis"] == 2 )
				++$yFieldsCount[ $value["strGroupField"] ];
		}

		foreach( $repGroupFields as $ind => $value )
		{
			$groupFields[ $ind ]["name"] = $value["strGroupField"];

			$xAxis = ($value["crossTabAxis"] == 0 || $value["crossTabAxis"] == 2);
			$yAxis = ($value["crossTabAxis"] == 1 || $value["crossTabAxis"] == 2);

			if( 0 == $value["groupInterval"] ||
				$xAxis && $xFieldsCount[ $value["strGroupField"] ] < 2 ||
				$yAxis && $yFieldsCount[ $value["strGroupField"] ] < 2 )
			{
				$groupFields[ $ind ]["label"] = $this->pSet->label( $value["strGroupField"] );
			}
			else
			{
				$groupFields[ $ind ]["label"] = $this->pSet->label( $value["strGroupField"] ) . " - " . CrossTableReport::getCrossIntervalName( $this->pSet->getFieldType( $value["strGroupField"] ), $value["groupInterval"] );

			}

			$groupFields[ $ind ]["uniqueName"] = true;
			$groupFields[ $ind ]["int_type"] = $value["groupInterval"];

			if( !$xNames[ $value["strGroupField"] ] )
				$xNames[ $value["strGroupField"] ] = array();

			if( !$yNames[ $value["strGroupField"] ] )
				$yNames[ $value["strGroupField"] ] = array();

			if( $value["crossTabAxis"] == 0 )
			{
				$groupFields[ $ind ]["group_type"] = "x";
				$xNames[ $value["strGroupField"] ][] = $ind;
			}
			elseif( $value["crossTabAxis"] == 1 )
			{
				$groupFields[ $ind ]["group_type"] = "y";
				$yNames[ $value["strGroupField"] ][] = $ind;
			}
			else
			{
				$groupFields[ $ind ]["group_type"] = "all";
				$xNames[ $value["strGroupField"] ][] = $ind;
				$yNames[ $value["strGroupField"] ][] = $ind;
			}
		}


		foreach( $xNames as $fName => $indices )
		{
			if( count( $indices ) > 1 )
			{
				foreach( $indices as $ind )
				{
					$groupFields[ $ind ]["uniqueName"] = false;
				}
			}
		}


		foreach( $yNames as $fName => $indices )
		{
			if( count( $indices ) > 1 )
			{
				foreach( $indices as $ind )
				{
					$groupFields[ $ind ]["uniqueName"] = false;
				}
			}
		}

		return $groupFields;
	}

	/**
	 * Get data for crosstab and assign with xt
	 * @param &Array _options
	 */
	public function setCrosstabData( &$_options )
	{
		if( $this->pSetSearch->noRecordsOnFirstPage() && !$this->isSearchFunctionalityActivated() )
		{
			$this->xt->assign("container_grid", false);
			$this->showNoRecordsMessage();
		}

		include_once( getabspath("classes/crosstable_report.php") );

		$params = array();

		$params["selectedAxis"] = $this->selectedAxis;
		$params["x"] = $this->x;
		$params["y"] = $this->y;
		$params["data"] = $this->dataField;
		$params["xType"] = $this->xType;
		$params["yType"] = $this->yType;
		$params["operation"] = $this->operation;

		$params["headerClass"] = $this->getFieldClass( $this->x );
		$params["dataClass"] = $this->getFieldClass( $this->dataField );

		$params["tableName"] = $this->tName;
		$params["pageType"] = $this->pageType;

		$params["groupFields"] = $this->getCrossGroupFieldsSettings( $_options["repGroupFields"] );

		$params["xSummary"] = $this->pSet->reportHasHorizontalSummary();
		$params["ySummary"] = $this->pSet->reportHasVerticalSummary();
		$params["totalSummary"] = $params["xSummary"] || $params["ySummary"];


		foreach( $_options["fieldsArr"] as $ind => $value )
		{
			$params["totals"][ $value["name"] ]["name"] = $value["name"];
			$params["totals"][ $value["name"] ]["label"] = $value["label"];

			$params["totals"][ $value["name"] ]["max"] = $value["totalMax"];
			$params["totals"][ $value["name"] ]["min"] = $value["totalMin"];
			$params["totals"][ $value["name"] ]["sum"] = $value["totalSum"];
			$params["totals"][ $value["name"] ]["avg"] = $value["totalAvg"];
		}

		if( $this->pdfJsonMode() )
			$params["pdfJSON"] = true;

		$this->crossTableObj = new CrossTableReport( $params, $this );

		if( $this->crosstableRefresh )
		{
			$this->refreshCrossTable();
			return;
		}

		if( $this->crossTableObj->isEmpty() )
		{
			$this->noRecordsFound = true;
			$this->jsSettings["tableSettings"][ $this->tName ]["crossParams"] = $this->getCurrentCrossParams();
		}

		$this->crossTableCommonAssign( $params["totalSummary"] );
	}

	/**
	 *
	 */
	protected function refreshCrossTable()
	{
		$reportData = array();

		$reportData["rowsInfo"] = $this->crossTableObj->getCrossTableData();
		$reportData["totalsName"] = $this->crossTableObj->getTotalsName();
		$reportData["columnSummary"] = $this->crossTableObj->getCrossTableSummary();
		$reportData["totalSummary"] = $this->crossTableObj->getTotalSummary();

		$reportData["groupFuncCtrl"] = $this->getOperationCtrlMarkup();
		$reportData["dataClass"] = $this->getFieldClass( $this->dataField );

		echo printJSON( $reportData );
		exit();
	}

	/**
	 * @param String axis
	 * @return String
	 */
	protected function getCrossFieldCtrlMarkup( $axis )
	{
		$classAttr = "form-control bs-cross-dd".$axis;

		$options = array();
		$lastLabel = "";
		foreach( $this->crossTableObj->getCrossFieldsData( $axis ) as $fData )
		{
			$intervalDataAttr = $fData["intervalType"] ? " data-".$axis."type=\"". $fData["intervalType"] ."\" " : "";
			$lastLabel = $fData["label"];
			$options[] = "<option ". $intervalDataAttr ." value=\"".$fData["value"]."\" ".$fData["selected"].">".$lastLabel."</option>";
		}

		$hiddenAttr = "";
		$labelTag = "";
		if ( count($options) < 2 )
		{
			$labelTag = "<span class=\"" . $classAttr . " like-text\">". $lastLabel ."</span>";
			$hiddenAttr = "style=\"display: none;\"";
		}

		return "<select ".$hiddenAttr." id=\"select_group_" . $axis . $this->id."\" class=\"" . $classAttr . "\">". implode("", $options) ."</select>" . $labelTag ;
	}

	/**
	 * @return String
	 */
	protected function getDataFieldCtrlMarkup()
	{
		$classAttr = "form-control bs-cross-ddvalue";

		$options = array();
		$lastLabel = "";
		foreach( $this->crossTableObj->getDataFieldsList() as $fData )
		{
			$lastLabel = runner_htmlspecialchars( $fData["label"] );
			$options[] = "<option value=\"". $fData["value"] ."\" ". $fData["selected"] .">". $lastLabel ."</option>";
		}

		$hiddenAttr = "";
		$labelTag = "";
		if ( count($options) < 2 )
		{
			$labelTag = "<span class=\"" . $classAttr . " like-text\">". $lastLabel ."</span>";
			$hiddenAttr = "style=\"display: none;\"";
		}

		return "<select ".$hiddenAttr." id=\"select_data".$this->id."\" class=\"" . $classAttr . "\">". implode("", $options) ."</select>" . $labelTag;


	}

	/**
	 * @deprecated
	 * @return String
	 */
	protected function getOldOperationCtrlMarkup()
	{
		$inputCtrls = array();
		foreach( $this->crossTableObj->getCurrentOperationList() as $opData )
		{
			$cheked = $opData["selected"] == "selected" ? "checked" : "";
			$inputCtrls[] = "<input type=radio value='".$opData["value"]."' name=\"group_func".$this->id."\" ".$cheked."> ".$opData["label"];
		}

		return implode( "&nbsp;&nbsp;", $inputCtrls );
	}

	/**
	 * @return String
	 */
	protected function getOperationCtrlMarkup()
	{
		$options = array();
		$lastLabel = "";
		foreach( $this->crossTableObj->getCurrentOperationList() as $opData )
		{
			$lastLabel = runner_htmlspecialchars( $opData["label"] );
			$options[] = "<option value=\"". $opData["value"] ."\" ". $opData["selected"] .">". $lastLabel ."</option>";
		}

		if ( count($options) < 2 )
			return  "<span id=\"group_func". $this->id."\" class=\"bs-cross-ddgroup form-control like-text\">". $lastLabel ."</span>";

		return "<select id=\"group_func". $this->id ."\" class=\"bs-cross-ddgroup form-control\">". implode("", $options) ."</select>";
	}

	/**
	 * Assign values obtained from crossTable object to
	 * the basic cross table xt variables
	 * @param Boolean showSummary
	 */
	protected function crossTableCommonAssign( $showSummary )
	{
		$this->xt->assign( "cross_controls", true );

		$this->xt->assign( "select_group_x", $this->getCrossFieldCtrlMarkup("x") );
		$this->xt->assign( "select_group_y", $this->getCrossFieldCtrlMarkup("y") );
		$this->xt->assign("select_data", $this->getDataFieldCtrlMarkup() );
		$this->xt->assign( "select_group", $this->getOperationCtrlMarkup() );

		$this->hideItemType("details_found");
		$this->hideItemType("page_size");


		$this->xt->assign( "totals", $this->crossTableObj->getTotalsName() );

		$grid_row["data"] = $this->crossTableObj->getCrossTableData();

		if( !Security::permissionsAvailable() ) {
			$allow_export = true;
		} else {
			$allow_export = $this->permis[ $this->tName ]["export"];
		}
		$this->xt->assign( "export_link", $allow_export && !$this->noRecordsFound );

		$this->xt->assign( "prints_block", $this->printAvailable() && !$this->noRecordsFound );

		if ( !$this->isDashboardElement() )
			$this->xt->assign("print_friendly", $this->printAvailable() && !$this->noRecordsFound );


		if( !$this->noRecordsFound )
		{
			$this->xt->assign("grid_row", $grid_row);
			$headers = $this->crossTableObj->getCrossTableHeader();
			$this->xt->assignbyref("group_header", $headers );
			$this->xt->assignbyref("col_summary", $this->crossTableObj->getCrossTableSummary());
			$this->xt->assignbyref("total_summary", $this->crossTableObj->getTotalSummary());
			$this->xt->assignbyref("summary_class", $this->getFieldClass( $this->dataField ));
			$this->xt->assign("cross_totals", $showSummary);

			$headerColspan = count( $grid_row["data"][0]["row_record"]["data"] );

			if( $grid_row["data"][0]["row_record"]["cross_totals"] )
				++$headerColspan;

			if( $headerColspan > 1 )
				$this->xt->assign( "xselcell_attrs", "colspan=".$headerColspan );
		}

		$this->xt->assign( "grid_header", !$this->noRecordsFound );

		//$this->xt->assign("crosstable_attrs", "&x=".$this->x."&y=".$this->y."&data=".$this->dataField."&op=".$this->operation);
	}


	/**
	 * Get data for standart report and assign with xt
	 * @param &Array _options
	 */
	public function setStandartData(&$_options)
	{
		include_once(getabspath('classes/reportlib.php'));

		$pageSize = $this->pageSize;
		if ( $this->pageSize == -1 ) {
			$pageSize = 0;
		}

		$rb = new Report( $this->pSet->getOrderIndexes(), $this->connection, $pageSize, 0, $_options, $this );

		$this->arrReport = $rb->getReport( $this->pagestart );

		$this->setRecordsId();
		$this->setDetailLinks();

		$this->buildPagination();

		$this->standardReportCommonAssign();
		$this->assignColumnHeaderClasses();
	}

	/**
	 * Get where clause for an active master-detail relationship
	 * @return string
	 */
	public function getMasterTableSQLClause()
	{
		if( $this->mode == REPORT_DASHBOARD && !isset($this->dashElementData["masterTable"]) )
			return "";
		return parent::getMasterTableSQLClause();
	}

	/**
	 * Assign the basic cross table xt variables
	 */
	protected function standardReportCommonAssign()
	{
		$this->xt->assign(GoodFieldName($this->tName)."_dtable_column", true); //fix it!
		$this->xt->assign("dtables_link", true);

		foreach($this->arrReport['page'] as $key => $value)
		{
			$this->xt->assign($key, $value);
		}

		foreach($this->arrReport['global'] as $key => $value)
		{
			$this->xt->assign($key, $value);
		}

		if( !!$this->arrReport['list'] )
			$this->xt->assign('grid_row', array('data' => $this->arrReport['list']));
		else
			$this->noRecordsFound = true;

		if( !Security::permissionsAvailable() ) {
			$allow_export = true;
			$allow_search = true;
		} else {
			$allow_export = $this->permis[ $this->tName ]["export"];
			$allow_search = $this->permis[ $this->tName ]["search"];
		}
		$this->xt->assign("export_link", $allow_export && $this->arrReport['countRows'] > 0);
		$this->xt->assign("prints_block", $allow_export && $this->arrReport['countRows'] > 0);
		$this->xt->assign("printall_link", $allow_export && $this->arrReport['countRows'] > $this->pageSize && $this->pageSize > 0);
		$this->xt->assign("print_recspp", $this->pSet->getReportPrintGroupsPerPage() );

		if ( !$this->isDashboardElement() )
		{
			$this->xt->assign("print_friendly", $this->printAvailable() && $this->arrReport['countRows'] > 0 );
			$this->xt->assign("print_friendly_all", $this->printAvailable() && $this->arrReport['countRows'] > 0);
		}

		if( $this->mode == REPORT_SIMPLE && $allow_search && !!$this->arrGroupsPerPage )
		{
			$this->xt->assign("recordspp_block", true);
			$this->createPerPage();
		}


		$this->xt->assign("details_found", $this->arrReport['countRows'] != 0);

		if( $this->noRecordsFound )
		{
			$this->hideItemType("details_found");
			$this->hideItemType("page_size");
		}

		$this->xt->assign("details_block", $this->arrReport['countRows'] != 0);
		$this->xt->assign("records_found", $this->arrReport['countRows']);
		$this->xt->assign("pages_block", $this->arrReport['countRows'] != 0);
		$this->xt->assign("page", $this->myPage);
		$this->xt->assign("maxpages", $this->maxPages);


		$this->xt->assign( "global_summary", !$this->noRecordsFound );
		$this->xt->assign( "page_summary", !$this->noRecordsFound );
		$this->xt->assign( "summary_header", !$this->noRecordsFound );

		// tabular report
		$this->xt->assign( "grid_header", !$this->noRecordsFound );
	}

	/**
	 * Assign pagination_block, pagination xt variables
	 */
	public function buildPagination()
	{
		//	prepare for create pagination
		$this->maxPages = $this->arrReport['maxpages'];

		$lastrecord = $this->myPage * $this->pageSize;
		if( $this->pageSize < 0 || $lastrecord > $this->arrReport['countRows'] )
			$lastrecord = $this->arrReport['countRows'];

		$this->prepareRecordsIndicator( ( $this->myPage - 1 ) * $this->pageSize + 1, $lastrecord, $this->arrReport['countRows'] );

		$separator = "";
		$advSeparator = "";

		if($this->maxPages > 1)
		{
			$this->xt->assign("pagination_block", true);
			$pagination = '';
			$limit = 10;
			if( $this->mobileTemplateMode() )
				$limit = 5;

			$counterstart = $this->myPage - ($limit - 1);
			if($this->myPage % $limit != 0)
				$counterstart = $this->myPage -($this->myPage % $limit) + 1;

			$counterend = $counterstart + ($limit - 1);
			if($counterend > $this->maxPages)
				$counterend = $this->maxPages;

			if($counterstart != 1)
			{
				$pagination.= $this->getPaginationLink(1, "First").$advSeparator;
				$pagination.= $this->getPaginationLink($counterstart - 1, "Previous").$separator;
			}

			$pageLinks = "";

			for($counter = $counterstart; $counter <= $counterend; $counter ++)
			{
				$pageLinks .= $separator . $this->getPaginationLink($counter,$counter, $counter == $this->myPage );
			}

			$pagination.= $pageLinks;

			if($counterend != $this->maxPages)
			{
				$pagination.= $separator . $this->getPaginationLink($counterend + 1, "Next") . $advSeparator;
				$pagination.= $separator . $this->getPaginationLink($this->maxPages, "Last");
			}

			$pagination = '<nav><ul class="pagination" data-function="pagination' . $this->id . '">' . $pagination . '</ul></nav>';

			$this->xt->assign("pagination", $pagination);
		}
		else if( !$this->myPage )
		{
			$this->myPage = 1; //temporary fix
		}
	}

	protected function setRecordsId() {
		$recCount = count( $this->arrReport['list'] );
		for( $i = 0; $i < $recCount; ++$i ) {
			$this->genId();
			$this->arrReport['list'][$i]["recId"] = $this->recId;
		}
	}

	/**
	 * fix it!
	 */
	protected function setDetailLinks()
	{
		if( $this->mode == REPORT_DASHBOARD )
			return;

		//	no details in reports currently
		return;

		// set detail links
		foreach( $this->allDetailsTablesArr as $detailTableData )
		{
			// get perm for det tables
			$this->permis[ $detailTableData['dDataSourceTable'] ] = $this->getPermissions( $detailTableData['dDataSourceTable'] );
			// field names of detail keys of passed detail table, when current is master
			$this->detailKeysByD[] = $this->pSet->getDetailKeysByDetailTable( $detailTableData['dDataSourceTable'] );
		}

		$this->controlsMap['gridRows'] = array();
		$arrReportList = array();
		foreach ($this->arrReport['list'] as $key => $data)
		{
			if (!isset($data['row_data']))
				continue;
			$record = array();
			//$this->genId();
			$recId = $data["recId"];

			$gridRowInd = count($this->controlsMap['gridRows']);
			$this->controlsMap['gridRows'][$gridRowInd] = array();
			$this->controlsMap['gridRows'][$gridRowInd]['id'] = $recId;
			$this->controlsMap['gridRows'][$gridRowInd]['rowInd'] = $gridRowInd;
			//Add the connection with containing row. It's important for vertical layout's multiple records per row mode
			$this->controlsMap['gridRows'][$gridRowInd]['keyFields'] = array();
			$this->controlsMap['gridRows'][$gridRowInd]['keys'] = array();

			//	???
			for($i = 0; $i < count($tKeys); $i ++) {
				$this->controlsMap['gridRows'][$gridRowInd]['keyFields'][$i] = $tKeys[$i];
				$this->controlsMap['gridRows'][$gridRowInd]['keys'][$i] = $data[$tKeys[$i].'_value'];
			}

			$this->proccessDetailGridInfo($record, $data, $gridRowInd);
			$record["recordattrs"] = "data-record-id=\"".$recId."\"";
			//$record["recId"] = $recId;
			$record["rowattrs"] = " id=\"gridRow".$recId."\"";
			$arrReportList[$key] = array_merge_assoc($data, $record);
			$this->recIds[] = $recId;
		}

		foreach($arrReportList as $key => $data)
		{
			$this->arrReport['list'][$key] = $data;
		}
		// end set detail links
	}


	/**
	 * Prepare detail for edit and view
	 */
	public function prepareDetailsForEditViewPage()
	{
		$this->addButtonHandlers();
		$this->commonAssign();

		$this->setReportData( $this->getExtraReportParams() );
		$this->xt->assign("cross_controls", false);


		$this->xt->assign("grid_block", true);
		$this->xt->assign("recordspp_block", true);

		$this->doCommonAssignments();

		$this->createPerPage();


		$this->body["begin"] = '';
		$this->body["end"] = '';
		$this->xt->assign("body", $this->body);
	}

	/**
	 * @return Array
	 */
	public function getExtraReportParams()
	{
		$extraParams = array();

		if( !$this->crossTable )
		{
			$extraParams['tName'] = $this->tName;
			$extraParams['shortTName'] = $this->shortTableName;
			$extraParams['sessionPrefix'] = $this->sessionPrefix;
			$extraParams['shortTableName'] = $this->shortTableName;

			$extraParams['tKeyFields'] = $this->pSet->getTableKeys();
			$extraParams['repPageSummary'] = $this->pSet->reportHasPageSummary();
			$extraParams['repGlobalSummary'] = $this->pSet->reportHasGlobalSummary();
			$extraParams['repLayout'] = $this->pSet->getReportLayout();
			$extraParams['showGroupSummaryCount'] = $this->pSet->isGroupSummaryCountShown();
			$extraParams['repShowDet'] = $this->pSet->reportDetailsShown();
			// if any field used for totals
			$extraParams['isExistTotalFields'] = $this->pSet->reportTotalFieldsExist();
		}

		// report field info
		$extraParams['repGroupFields'] = $this->pSet->getReportGroupFieldsData();
		$extraParams['repGroupFieldsCount'] = count( $extraParams['repGroupFields'] );

		$paramfieldArr = array();
		$reportFields = $this->pSet->getFieldsList();
		foreach( $reportFields as $field )
		{
			$fieldArr = array();
			$fieldArr['name'] = $field;
			//'fName' added for maps
			$fieldArr['fName'] = $field;
			$fieldArr['label'] = $this->pSet->label( $field );
			$fieldArr['goodName'] = GoodFieldName( $field );
			$fieldArr['repPage'] = true; //"@f.bReportPage";
			$fieldArr['viewFormat'] = $this->pSet->getViewFormat( $field );
			$fieldArr['editFormat'] = $this->pSet->getEditFormat( $field );

			$fieldInfo = $this->pSet->reportFieldInfo( $field );
			if( $fieldInfo ) {
				$fieldArr['totalMax'] = !!$fieldInfo["max"];
				$fieldArr['totalMin'] = !!$fieldInfo["min"];
				$fieldArr['totalAvg'] = !!$fieldInfo["avg"];
				$fieldArr['totalSum'] = !!$fieldInfo["sum"];
			}
			$paramfieldArr[] = $fieldArr;
		}

		$extraParams['fieldsArr'] = $paramfieldArr;

		return $extraParams;
	}

	/**
	 * Assign recsPerPage, recsPerPage xt variables
	 */
	public function createPerPage()
	{
		$classString = 'class="form-control"';
		$allMessage = "All";

		$rpp = "<select ".$classString." id=\"recordspp".$this->id."\">";

		// use group fields on report page or not
		$reportGroupFields = $this->pSet->isReportWithGroups();

		if( $reportGroupFields )
		{
			for($i = 0; $i < count($this->arrGroupsPerPage); $i++)
			{
				if( $this->arrGroupsPerPage[$i] != -1 )
					$rpp.= "<option value=\"".$this->arrGroupsPerPage[$i]."\" ".($this->pageSize == $this->arrGroupsPerPage[$i] ? "selected" : "").">".$this->arrGroupsPerPage[$i]."</option>";
				else
					$rpp.= "<option value=\"-1\" ".($this->pageSize == $this->arrGroupsPerPage[$i] ? "selected" : "").">".$allMessage."</option>";
			}
		}
		else
		{
			for($i = 0; $i < count($this->arrRecsPerPage); $i++)
			{
				if( $this->arrRecsPerPage[$i] != -1 )
					$rpp.= "<option value=\"".$this->arrRecsPerPage[$i]."\" ".($this->pageSize == $this->arrRecsPerPage[$i] ? "selected" : "").">".$this->arrRecsPerPage[$i]."</option>";
				else
					$rpp.= "<option value=\"-1\" ".($this->pageSize == $this->arrRecsPerPage[$i] ? "selected" : "").">".$allMessage."</option>";
			}
		}

		$rpp.= "</select>";

		$this->xt->assign("grpsPerPage", $rpp);
	}

	/**
	 *
	 */
	public function doCommonAssignments() //make it protected
	{
		$this->xt->assign("left_block", true);

		$this->assignBody();

		$this->setLangParams();

		//set the Search panel
		$this->xt->assign("searchPanel", true);

		if( $this->isShowMenu() )
			$this->xt->assign("menu_block", true);

		if( $this->mobileTemplateMode() )
			$this->xt->assign('tableinfomobile_block', true);


		if( !Security::permissionsAvailable() ) {
			$allow_search = true;
			$allow_export = true;
		} else {
			$allow_search = $this->permis[ $this->tName ]["search"];
			$allow_export = $this->permis[ $this->tName ]["export"];
		}

		$this->xt->assign("grid_block", $allow_search);
		$this->xt->assign("toplinks_block", $allow_search);
		$this->xt->assign("asearch_link", $allow_search);

		$this->xt->assign("print_link", $allow_export);
		$this->xt->assign("printlink_attrs", "id=print_".$this->id." href='#'");
		$this->xt->assign("printalllink_attrs", "id=printAll_".$this->id." href='#'");

		$this->xt->assign("excellink_attrs", "id=export_to_excel".$this->id." href='#'");
		$this->xt->assign("wordlink_attrs", "id=export_to_word".$this->id." href='#'");
		$this->xt->assign("pdflink_attrs", "id=export_to_pdf".$this->id." href='#'");

		$this->xt->assign("advsearchlink_attrs", "id=\"advButton".$this->id."\"");

		if( $this->noRecordsFound )
			$this->showNoRecordsMessage();

		foreach( $this->pSet->getPageFields() as $f )
		{
			$gf = GoodFieldName($f);
			$this->xt->assign( $gf . "_class", $this->fieldClass( $f ));
			$this->xt->assign( $gf . "_align", $this->fieldAlign( $f ));
		}

		if( $this->pdfJsonMode() )
			$this->xt->assign( "pdfFonts", my_json_encode( getPdfFonts() ) );
	}

	/**
	 * Add common javascript files and code
	 */
	function addCommonJs()
	{
		parent::addCommonJs();
	}

	/**
	 *
	 */
	protected function assignBody()
	{
		$this->body["begin"].= GetBaseScriptsForPage( $this->isDisplayLoading );

		if( $this->mode == REPORT_SIMPLE && !$this->mobileTemplateMode() )
			$this->body["begin"].= "<div id=\"search_suggest\" class=\"search_suggest\"></div>";

		// assign body end in such way, to prevent collisions with flyId increment
		$this->body['end'] = XTempl::create_method_assignment( "assignBodyEnd", $this);

		$this->xt->assignbyref("body", $this->body);
	}

	/**
	 *
	 */
	public function beforeShowReport()
	{
		if( $this->eventsObject->exists("BeforeShowReport") )
			$this->eventsObject->BeforeShowReport($this->xt, $this->templatefile, $this);
	}

	/**
	 * Display the report page
	 */
	public function showPage()
	{
		$this->beforeShowReport();

		if( $this->mode == REPORT_SIMPLE )
		{
			$this->display( $this->templatefile );
			return;
		}

		$this->body["begin"] = '';
		$this->body["end"] = '';
		$this->xt->assign("body", $this->body);

		$this->xt->assign("header", false);
		$this->xt->assign("footer", false);

		if( $this->mode == REPORT_DASHBOARD )
		{
			$this->xt->prepare_template( $this->templatefile );

			$this->addControlsJSAndCSS();
			$this->fillSetCntrlMaps();

			$returnJSON = array();
			global $pagesData;
			$returnJSON["pagesData"] = $pagesData;
			$returnJSON['settings'] = $this->jsSettings;
			$returnJSON['controlsMap'] = $this->controlsHTMLMap;
			$returnJSON['viewControlsMap'] = $this->viewControlsHTMLMap;

			if( $this->formBricks["footer"] )
				$returnJSON["footerCont"] = $this->fetchBlocksList( $this->formBricks["footer"], true );
			if( $this->formBricks["header"] )
				$returnJSON["headerCont"] = $this->fetchBlocksList( $this->formBricks["header"], true );

			//	prepend headerCont with the page title
			$returnJSON['headerCont'] = '<span class="rnr-dbebrick">'
				. $this->getPageTitle( $this->pageName, GoodFieldName($this->tName) )
				. "</span>"
				. $returnJSON['headerCont'];

			$icon = getIconHTML( $this->dashElementData["item"]["icon"] );
			if( $icon )
				$returnJSON["iconHtml"] = $icon;


			$this->assignFormFooterAndHeaderBricks(false);
			$this->xt->prepareContainers();

			$returnJSON["html"] = $this->fetchBlocksList( array( "above-grid_block", "grid_tabs", "grid_block" ) );
			//$returnJSON["html"] = $this->xt->fetch_loaded("message_block").$this->xt->fetch_loaded("grid_block");

			$returnJSON['idStartFrom'] = $this->flyId;
			$returnJSON['success'] = true;

			$returnJSON["additionalJS"] = $this->grabAllJsFiles();
			$returnJSON["CSSFiles"] = $this->grabAllCSSFiles();

			echo printJSON($returnJSON);
			exit();
			return;
		}

		if( $this->mode == REPORT_DETAILS || $this->mode == REPORT_DASHDETAILS )
		{
			$this->showDpAjax();
			exit();
			return;
		}

		if( $this->mode && $this->mode == "listdetailspopup" ) //a currently unused option
		{
			$this->xt->assign("container_master", false);

			$this->xt->assign("cross_controls", false);
			$this->xt->prepare_template($this->templatefile);
			$respArr = array();
			$respArr['success'] = true;
			$respArr['body'] = $this->xt->fetch_loaded("body");
			$respArr['counter'] = postvalue('counter');

			echo printJSON($respArr);
			exit();
			return;
		}
	}

	/**
	 * Display the inline report preview in respone on an ajax-like request
	 */
	protected function showDpAjax()
	{
		$returnJSON = array();

		if( $this->mode == REPORT_DETAILS
			&& $this->dashTName
			&& $this->dashElementName
			&& !$this->shouldDisplayDetailsPage()
			&& ($this->masterPageType == PAGE_EDIT ||  $this->masterPageType == PAGE_VIEW)
			)
		{
			$returnJSON['noData'] = true;
			echo printJSON( $returnJSON );
			return;
		}

		if( $this->mode == REPORT_DETAILS
			&& $this->masterPageType == PAGE_LIST
			&& !$this->shouldDisplayDetailsPage()
			)
		{
			$returnJSON['success'] = false;
			echo printJSON( $returnJSON );
			return;
		}

		$this->xt->unassign("cross_controls");

		$this->hideElement("printpanel");


		$this->xt->prepare_template( $this->templatefile );

		$this->addControlsJSAndCSS();
		$this->fillSetCntrlMaps();

		global $pagesData;
		$returnJSON["pagesData"] = $pagesData;
		$returnJSON['settings'] = $this->jsSettings;
		$returnJSON['controlsMap'] = $this->controlsHTMLMap;
		$returnJSON['viewControlsMap'] = $this->viewControlsHTMLMap;

		if( $this->formBricks["footer"] )
			$returnJSON["footerCont"] = $this->fetchBlocksList( $this->formBricks["footer"], true );
		if( $this->formBricks["header"] )
			$returnJSON["headerCont"] = $this->fetchBlocksList( $this->formBricks["header"], true );

		if( $this->mode == REPORT_DETAILS && ( $this->masterPageType == PAGE_LIST || $this->masterPageType == PAGE_REPORT || $this->masterPageType == PAGE_CHART ) )
		{
			$returnJSON['headerCont'] = $this->getProceedLink()	. $returnJSON['headerCont'];
		}
		else if( $this->mode == REPORT_DASHDETAILS )
		{
			//	prepend headerCont with the page title
			$returnJSON['headerCont'] = '<span class="rnr-dbebrick">'
				. $this->getPageTitle( $this->pageName, GoodFieldName($this->tName) )
				. "</span>"
				. $returnJSON['headerCont'];
		}
		$icon = getIconHTML( $this->dashElementData["item"]["icon"] );
		if( $icon )
			$returnJSON["iconHtml"] = $icon;

		$this->assignFormFooterAndHeaderBricks(false);
		$this->xt->prepareContainers();

		$returnJSON["html"] = $this->xt->fetch_loaded("grid_tabs").
			//$this->xt->fetch_loaded("message_block").
			$this->xt->fetch_loaded("grid_block").
			$this->xt->fetch_loaded("pagination_block");

		$returnJSON['success'] = true;
		$returnJSON['id'] = $this->id;
		$returnJSON['idStartFrom'] = $this->flyId;

		$returnJSON["additionalJS"] = $this->grabAllJsFiles();
		$returnJSON["additionalCSS"] = $this->grabAllCSSFiles();

		echo printJSON( $returnJSON );
	}

	/**
	 *
	 */
	function printAvailable()
	{
		if( $this->mode == REPORT_DASHBOARD || $this->mode == REPORT_DETAILS || $this->mode == REPORT_DASHDETAILS )
			return false;
		return RunnerPage::printAvailable();
	}

	/**
	 * Show a detail preview page
	 * @param Array params - asp compatibility issue
	 */
	function showPageDp($params = "")
	{
		if( $this->crossTable )
			$this->xt->unassign("cross_controls");

		parent::showPageDp( $params );
	}

	public function prepareDisplayDetails() {
		$this->prepareDisplayDetailsPD();
	}

	public function prepareDisplayDetailsPD()
	{
		if( $this->pdfJsonMode() ) {
			$this->xt->assign("embedded_grid", true );
			$this->xt->assign("embedded_page_title", true );

			$this->xt->load_templateJSON( $this->templatefile);
			$this->renderedBody = $this->xt->fetch_loadedJSON("body");
			return;
		}

		$forms = array( "grid" );
		$bodyContents = $this->fetchForms($forms);
		$this->renderedBody = '<div id="detailPreview'.$this->id.'">'.$bodyContents.'</div>';
	}

	public function showGridOnly()
	{
		echo $this->renderedBody;
	}

	/**
	*
	*/
	function shouldDisplayDetailsPage()
	{
		if( !$this->permis[$this->tName]['search'] )
			return false;

		if( $this->noRecordsFound && 0 == $this->getGridTabsCount() )
			return false;

		return true;
	}

	/**
	 * @param String field
	 * @return String
	 */
	protected function getFieldClass( $field )
	{
		$class = parent::fieldClass( $field );

		if( $this->crossTable ) {
			if( in_array( $this->pSet->getViewFormat( $field ), array( FORMAT_DATE_SHORT, FORMAT_DATE_LONG, FORMAT_DATE_TIME ) ) )
				return $class." rnr-field-crossdate";
		}

		return $class;
	}

	/**
	 * @return String
	 */
	public static function readReportModeFromRequest()
	{
		$mode = postvalue("mode");
		if( $mode == "listdetails" )
			$pageMode = REPORT_DETAILS;
		else if( $mode == "listdetailspopup" )
			$pageMode = REPORT_POPUPDETAILS;
		else if( $mode == "dashreport" )
			$pageMode = REPORT_DASHBOARD;
		else if ( $mode == "dashdetails" )
			$pageMode = REPORT_DASHDETAILS;
		else
			$pageMode = REPORT_SIMPLE;

		return $pageMode;
	}

	function gridTabsAvailable() {
		return true;
	}

	function displayTabsInPage()
	{
		return $this->simpleMode() 
			|| ( $this->mode == REPORT_DETAILS && ($this->masterPageType == PAGE_VIEW || $this->masterPageType == PAGE_EDIT))
			|| $this->mode == REPORT_DASHBOARD && $this->dashElementData["tabLocation"] == "body";;
	}		

	function renderPageBody()
	{
		$blocks = array("grid_tabs", "message", "grid_block", "pagination_block");
		return $this->fetchBlocksList($blocks, false);

	}

	protected function assignColumnHeaderClasses()
	{
		$reportFields = $this->pSet->getFieldsList();
		foreach( $reportFields as $field )
		{
			$goodName = GoodFieldname($field);
			$this->xt->assign("fieldclass_".$goodName, $this->getFieldClass($field) );
			$this->xt->assign($goodName . "_align", $this->fieldAlign($field));

		}
	}

	function pdfJsonMode()
	{
		return $this->pdfJson;
	}

	public function getSubsetDataCommand( $ignoreFilterField = "" ) {

		$dc = parent::getSubsetDataCommand();

		//	no records on first page
		if( $this->mode != REPORT_DETAILS && $this->pSet->noRecordsOnFirstPage() && !$this->isSearchFunctionalityActivated() )
			$dc->filter = DataCondition::_False();

		return $dc;
	}

}
?>