<?php

use Vn\Lib;

/**
 * Adds a document to the Document Management System.
 **/
class Add extends Vn\Web\JsonRequest {
	function run($db) {
		// XXX: Uncomment only to test the script
		//$_REQUEST['description'] = 'description';
		
		$description = empty($_REQUEST['description']) ?
			NULL : $_REQUEST['description']; 
		
		$baseDir = _DATA_DIR .'/'. $this->app->getName();
		$docsDir = "$baseDir/dms";
		$tempDir = "$baseDir/.dms";

		$digXDir = 3;
		$zerosDir = '';
		
		for ($i = 0; $i < $digXDir; $i++)
			$zerosDir .= '0';
		
		// Checks document restrictions
		
		if (empty($_FILES['doc']['name']))
			throw new Lib\UserException('File not choosed');

		$maxSize = $db->getValue('SELECT max_size FROM dms_config');

		if ($_FILES['doc']['size'] > $maxSize * 1048576)
			throw new Lib\UserException(sprintf('File size exceeds size: %d MB', $maxSize));

		try {
			// Registers the document in the database

			$db->query('START TRANSACTION');

			$db->query('INSERT INTO dms_document SET description = #', [$description]);	
			$docId =(string) $db->getValue('SELECT LAST_INSERT_ID()');
		
			$len = strlen($docId);
			$neededLevels = ceil($len / $digXDir) - 1;

			$dirLevels = $db->getValue(
				'SELECT dir_levels FROM dms_config LOCK IN SHARE MODE');

			if ($dirLevels > $neededLevels)
				$neededLevels = $dirLevels;

			// Reorganizes the file repository if necessary

			if ($dirLevels < $neededLevels)
				$dirLevels = $db->getValue(
					'SELECT dir_levels FROM dms_config FOR UPDATE');

			if ($dirLevels < $neededLevels) {
				if (is_dir($docsDir)) {
					$dif =($neededLevels - $dirLevels) - 1;
					$newDir = $docsDir;
				
					for ($i = 0; $i < $dif; $i++)
						$newDir .= "/$zerosDir";
		
					$success = rename($docsDir, $tempDir)
						&& mkdir($newDir, 0770, TRUE)
						&& rename($tempDir, "$newDir/$zerosDir");

					if (!$success)
						throw new Exception('Error while reorganizing directory tree');
				}

				$curLevels = $db->query('UPDATE dms_config SET dir_levels = #',
					[$neededLevels]);
			}

			// Saves the document to the repository

			$padLen =($neededLevels + 1) * $digXDir;
			$paddedId = str_pad($docId, $padLen, '0', STR_PAD_LEFT);
		
			$saveDir = $docsDir;
		
			for ($i = 0; $i < $neededLevels; $i++)
				$saveDir .= '/'. substr($paddedId, $i * $digXDir, $digXDir);

			if (!file_exists($saveDir))
				mkdir($saveDir, 0770, TRUE);
			
			$savePath = "$saveDir/". substr($paddedId, -$digXDir);
	
			move_uploaded_file($_FILES['doc']['tmp_name'], $savePath);

			$db->query('COMMIT');

			return $docId;
		} catch (Exception $e) {
			$db->query('ROLLBACK');
			throw $e;
		}
	}
}