<?php

// h-source, a web software to build a community of people that want to share their hardware information.
// Copyright (C) 2010  Antonio Gallo (h-source-copyright.txt)
//
// This file is part of h-source
//
// h-source is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// h-source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with h-source.  If not, see <http://www.gnu.org/licenses/>.

if (!defined('EG')) die('Direct access not allowed!');

class HardwareModel extends Model_Map {

	public $id_user = 0;
	public $type = ''; //device type
	public $lastId = 0; //the id of the last record inserted

	public $formStruct = array(
		'entries' 	=> 	array(
			'deleted'=>	array('type'=>'Select','options'=>'no,yes'),
			'id_hard'		=>	array(
				'type'		=>	'Hidden'	
			)
		),
	);

	public function __construct() {
		$this->_tables='hardware,regusers,hardware_users';
		$this->_idFields='id_hard,id_user';
		$this->_where=array(
			'type'				=>	'hardware',
			'username'			=>	'regusers',
			'id_user'			=>	'regusers',
			'has_confirmed'		=>	'regusers',
			'deleted'			=>	'regusers',
			'-deleted'			=>	'hardware'
		);
		$this->orderBy = 'hardware.id_hard desc';
		$this->printAssError = "no";
		
		$this->_popupItemNames = array(
			'type'=>'type',
			'ask_for_del'=>'ask_for_del',
			'-deleted'=>'deleted',
		);
		
		$this->_popupLabels = array(
			'type'=>'TYPE',
			'ask_for_del'=>'ASK FOR DEL?',
			'-deleted'=>'DELETED?',
		);
		
// 		$this->databaseConditions['insert'] = array(
// 			'checkUnique'		=>	'model',
// 		);
// 		
// 		$this->databaseConditions['update'] = array(
// 			'checkUniqueCompl'	=>	'model',
// 		);

		parent::__construct();
	}

	//set the soft and strong conditions
	public function setConditions($worksOptions,$worksField,$interfaceOptions)
	{
		$this->strongConditions['update'] = array(
			"checkNotEmpty"								=>	"model|you have to fill the <i>model name</i> entry",
			"checkMatch|".Hardware::$regExpressions['model']	=>	"model|characters not allowed in the <i>model name</i> entry",
			"+checkMatch|".Hardware::$regExpressions['vendorid_productid']	=>	"pci_id|<i>VendorID:ProductID</i> has to have the following format: [a-zA-Z0-9]{4}(\:)[a-zA-Z0-9]{4}",
			"checkLength|190"	=>	"model",
			"+checkLength|299"	=>	"distribution",
			"++checkIsStrings|".Hardware::getCommYears()	=> 	"comm_year",
			"+++checkIsStrings|".$worksOptions 	=> 	$worksField,
			"++++checkIsStrings|".$interfaceOptions	=> 	"interface",
		);

		$this->strongConditions['insert'] = $this->strongConditions['update'];

		$this->softConditions['update'] = array(
			"checkMatch|".Hardware::$regExpressions['kernel']	=>	"kernel|characters not allowed in the <i>kernel</i> entry",
			"checkLength|40000"	=>	"description",
			"+checkLength|49"	=>	"kernel",
			"++checkLength|49"	=>	"driver",
			"++checkMatch|".Hardware::$regExpressions['driver']	=>	"driver|only the following characters are allowed for the <i>driver</i> entry: a-z A-Z 0-9 - _ . + s / , : ; ( ) [ ]",
			"+++checkLength|1000"	=>	"other_names|the <i>other names</i> entry exceeds the value of 1000 characters",
		);

		$this->softConditions['insert'] = $this->softConditions['update'];
	}

	public function permanentlyDelete($id)
	{
		$clean['id'] = (int)$id;
		
		$record = $this->selectId($clean['id']);
		
		$this->values['deleted'] = 'no';
		$this->values['approved'] = 'yes';
		$this->values['pci_id'] = '';
		$this->values['model'] = '[permanently deleted] '.$record['model'];
		
		return parent::update($clean['id']);
	}

	public function pUpdate($id)
	{
		if (isset($this->values['approved']))
		{
			if (strcmp($this->values['approved'],'yes') === 0)
			{
				$this->values['deleted'] = 'no';
			}
		}
		else if (isset($this->values['deleted']))
		{
			if (strcmp($this->values['deleted'],'no') === 0)
			{
				$this->values['approved'] = 'yes';
			}
		}
		return parent::update($id);
	}
	
	public function insert()
	{
		$this->values['created_by'] = (int)$this->id_user;
		$this->values['updated_by'] = (int)$this->id_user;
		$this->values['update_date'] = date('Y-m-d H:i:s');

		if ($this->values['created_by'] === 0)
		{
			$this->values['deleted'] = 'yes';
			$this->values['approved'] = 'no';
		}
		
		//random ID
		$randomId = md5(uniqid(mt_rand(),true));
		$this->values["type"] = $randomId;

		parent::insert();
// 		echo $this->getQuery();
		//associate the user to the record
		if ($this->queryResult)
		{
			$resId = $this->db->select("hardware","id_hard","type='$randomId'");
			$clean['id'] = $resId[0]['hardware']['id_hard'];
			$this->lastId = $clean['id'];
			$this->db->update('hardware','type',array($this->type),'id_hard='.$clean['id']);

			//update the history table
			$this->updateHistory('insert');

			if ($this->values['created_by'] !== 0)
			{
				$this->associate($clean['id']);
			}
		}
		 
	}

	public function update($id)
	{
		$clean['id'] = (int)$id;
		
		$this->values['updated_by'] = (int)$this->id_user;
		$this->values['update_date'] = date('Y-m-d H:i:s');
		
		//save the old fields in the revisions table
		$this->setWhereQueryClause(array('id_hard'	=>	$clean['id']));
		$oldStruct = $this->getFields($this->fields.',vendor,created_by,updated_by,update_date,type,id_hard');
		
		if (count($oldStruct > 0))
		{
			if (strcmp($oldStruct[0]['hardware']['type'],$this->type) === 0)
			{
				$oldValues = $oldStruct[0]['hardware'];
				
				$revisions = new RevisionsModel();
				$revisions->values = $oldValues;
				$revisions->sanitize();
				
				if ($revisions->insert())
				{
					parent::update($clean['id']);
					if ($this->queryResult)
					{
						$this->lastId = $clean['id'];

						//update the history table
						$this->updateHistory('update');
			
						if (!$this->checkAssociation($clean['id'],(int)$this->id_user))
						{
							$this->associate($clean['id']);
						}
					}
				}
			}
		}
	}

	public function makeCurrent($id_rev)
	{
		$clean['id_rev'] = (int)$id_rev;
		
		$revisions = new RevisionsModel();
		
		$clean['id_hard'] = (int)$revisions->getIdHard($clean['id_rev']);
		
		//save the old fields in the revisions table
		$this->setWhereQueryClause(array('id_hard'=>$clean['id_hard']));
		$oldStruct = $this->getFields($this->fields.',vendor,created_by,updated_by,update_date,type,id_hard');
		
		if (count($oldStruct > 0))
		{
			if (strcmp($oldStruct[0]['hardware']['type'],$this->type) === 0)
			{
				//get the values of the revision
				$revisions->setWhereQueryClause(array('id_rev'=>$clean['id_rev']));
				$newStruct = $revisions->getFields($this->fields.',vendor,created_by,updated_by,update_date,type');
				
				if (count($newStruct > 0))
				{
					$revisions->values = $oldStruct[0]['hardware'];
					$revisions->sanitize();
					
					$this->values = $newStruct[0]['revisions'];
					$this->values['updated_by'] = (int)$this->id_user;
					$this->values['update_date'] = date('Y-m-d H:i:s');

					$this->sanitize();
					
					if ($revisions->insert())
					{
						if (parent::update($clean['id_hard']))
						{
							$this->lastId = $clean['id_hard'];
							
							//update the history table
							$this->updateHistory('update');
							
							if (!$this->checkAssociation($clean['id_hard'],(int)$this->id_user))
							{
								$this->associate($clean['id_hard']);
							}
						}
					}
				}
			}
			else
			{
				$this->notice = "<div class='alert'>Wrong type..</div>\n";
			}
		}
		
	}

	public function associate($id_record)
	{
		return parent::associate((int)$id_record,(int)$this->id_user);
	}

	//get the model name
	public function getTheModelName($id)
	{
		$clean['id'] = (int)$id;
		$this->setWhereQueryClause(array('id_hard' => $clean['id']));
		$res = $this->getFields('model');
		$name = count($res) > 0 ? $res[0]['hardware']['model'] : '';
		return $name;
	}

	//get the model info by the vendorid:productid code
	public function getModelByCode($code)
	{
		$res = $this->clear()->where(array('pci_id'=>sanitizePciid($code)))->send();

		if (count($res) > 0)
		{
			return $res[0]['hardware'];
		}
		return false;
	}

	//save in the history all the action carried out by users
	protected function updateHistory($action)
	{
		$translations = array(
			'insert'		=>	'inserted',
			'update'		=>	'updated',
		);

		$allowedActions = array('insert','update');

		if (in_array($action,$allowedActions))
		{
			$users = new UsersModel();

			$clean['user'] = sanitizeAll($users->getUser($this->id_user));
			
			$history = new HistoryModel();
			$history->values = array(
				'created_by' 	=>	$this->id_user,
				'type'			=>	'hardware',
				'action'		=>	$action,
				'id'			=>	$this->lastId,
				'message'		=>	'The device having id='.$this->lastId.' has been '.$translations[$action].' by the user ' . $clean['user'] . ' (id_user='.$this->id_user.') ',
				'gr'			=>	'registered',
			);
			$history->insert();
		}
	}

	public function isDeleted($id)
	{
		$clean['id'] = (int)$id;
		$res = $this->select('hardware.deleted')->where(array('id_hard'=>$clean['id']))->send();
		if ( count($res) > 0 )
		{
			return strcmp($res[0]['hardware']['deleted'],'no') === 0 ? false : true;
		}
		return false;
	}

	public function isCleared($id)
	{
		$clean['id'] = (int)$id;
		$res = $this->select('hardware.cleared')->where(array('id_hard'=>$clean['id']))->send();
		if ( count($res) > 0 )
		{
			return strcmp($res[0]['hardware']['cleared'],'no') === 0 ? false : true;
		}
		return false;
	}
	
}