<?php

use FileRun\Files\Plugin;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Utils;
use GuzzleHttp\Exception;

class custom_zamzar extends Plugin {

	var $online = true;
	var string $urlBase = 'https://sandbox.zamzar.com/v1';
	static $localeSection = 'Custom Actions: Zamzar';
	static $publicMethods = ['requestConversion', 'getStatus', 'downloadConverted'];

	function init() {
		$this->settings = [
			[
				'key' => 'APIKey',
				'title' => self::t('API key'),
				'width' => '100%',
				'comment' => self::t('Get it from %1', ['<a href="https://developers.zamzar.com" target="_blank">https://developers.zamzar.com</a>'])
			]
		];
		$this->JSconfig = [
			"title" => self::t("Zamzar"),
			'icon' => 'images/icons/zamzar.png',
			"popup" => true,
			'width' => 580,
			'height' => 400,
			"requiredUserPerms" => ["download", "upload"],
			"requires" => ["download", "upload"]
		];
	}

	function isDisabled() {
		return (strlen(self::getSetting('APIKey')) == 0);
	}

	function run() {
		require $this->path."/display.php";
	}

	function requestConversion() {
		$filePointer = $this->readFile(['returnFilePointer' => true]);

		$url = $this->urlBase.'/jobs';
		$http = new Client();
		try {
			$response = $http->request('POST', $url, [
				'auth' => [self::getSetting('APIKey'), ''],
				'multipart' => [
					[
						'name'     => 'target_format',
						'contents' => $_POST['format']
					],
					[
						'name'     => 'source_file',
						'contents' => $filePointer
					]
				]
			]);
		} catch (Exception\ConnectException $e) {
			jsonFeedback(false, 'Network connection error: '.$e->getMessage());
		} catch (Exception\ClientException $e) {
			$rs = json_decode($e->getResponse()->getBody()->getContents(), true);
			jsonFeedback(false, 'Client error: '.$e->getResponse()->getStatusCode().' - '. $rs['errors'][0]['message']);
		} catch (Exception\ServerException $e) {
			$rs = json_decode($e->getResponse()->getBody()->getContents(), true);
			jsonFeedback(false, 'Server error: '.$e->getResponse()->getStatusCode().' - '.$rs['errors'][0]['message']);
		} catch (\RuntimeException $e) {
			jsonFeedback(false, 'Error: '.$e->getMessage());
		}
		$rs = $response->getBody()->getContents();
		if (!$rs) {
			jsonFeedback(false, 'Error requesting conversion: empty server response!');
		}
		$rs = json_decode($rs, true);
		if (!is_array($rs)) {
			self::outputError('Unexpected response from the ZamZar server!');
		}
		if (!$rs['id']) {
			self::outputError('Missing ZamZar conversion job id!');
		}
		jsonOutput([
			'success' => true,
			'msg' => 'Zamzar: '. $rs['status'],
			'jobId' => $rs['id']
		]);
	}

	function getStatus() {
		$url = $this->urlBase.'/jobs/'.S::forURL($_POST['jobId']);

		$http = new Client();
		try {
			$response = $http->request('GET', $url, [
				'auth' => [self::getSetting('APIKey'), '']
			]);
		} catch (Exception\ConnectException $e) {
			jsonFeedback(false, 'Network connection error: '.$e->getMessage());
		} catch (Exception\ClientException $e) {
			$rs = json_decode($e->getResponse()->getBody()->getContents(), true);
			jsonOutput(array(
				'success' => false,
				'msg' => 'Zamzar status: '.$rs['status'],
				'status' => $rs['status']
			));
		} catch (Exception\ServerException $e) {
			echo 'Server error: '.$e->getResponse()->getStatusCode();
			exit();
		} catch (\RuntimeException $e) {
			echo 'Error: '.$e->getMessage();
			exit();
		}
		$rs = $response->getBody()->getContents();
		if (!$rs) {
			jsonFeedback(false, 'Error checking status: empty server response!');
		}
		$rs = json_decode($rs, true);

		$rs['output']['size'] = \FM::formatFileSize($rs['output']['size']);
		jsonOutput(array(
			'success' => true,
			'msg' => 'Zamzar: '.$rs['status'],
			'status' => $rs['status'],
			'fileId' => $rs['target_files'][0]['id']
		));
	}

	function downloadConverted() {
		$ext = \FM::getExtension($this->data['fileName']);
		$newExt = $_POST['format'];
		if ($newExt == $ext) {
			$newExt = ' (converted) '.$newExt;
		}
		$newName = \FM::replaceExtension($this->data['fileName'], $newExt);
		$this->data['relativePath'] = \FM::newName($this->data['relativePath'], $newName);
		$data = $this->prepareWrite();
		$tempFilePath = $data['fullPath'].'.zamzar.tmp';
		$writeStream = fopen($tempFilePath, "wb");
		if ($writeStream === false) {
			jsonFeedback(false, 'Failed to create temporary file!');
		}
		$http = new Client();
		$local = Utils::streamFor($writeStream);
		$url = $this->urlBase.'/files/'.S::forURL($_POST['fileId']).'/content';
		try {
			$response = $http->request('GET', $url,
				[
				'auth' => [self::getSetting('APIKey'), ''],
				'sink' => $local
			]);
		} catch (Exception\ConnectException $e) {
			jsonFeedback(false, 'Network connection error: '.$e->getMessage());
		} catch (Exception\ClientException $e) {
			$rs = json_decode($e->getResponse()->getBody()->getContents(), true);
			jsonOutput([
				'success' => false,
				'msg' => 'Zamzar status: '.$rs['status'],
				'status' => $rs['status']
			]);
		} catch (Exception\ServerException $e) {
			jsonFeedback(false, 'Server error: '.$e->getResponse()->getStatusCode());
		} catch (\RuntimeException $e) {
			jsonFeedback(false, 'Error: '.$e->getMessage());
		}
		if ($response->getStatusCode() == 200) {
			fclose($writeStream);
			$this->writeFile([
				'source' => 'move',
				'moveFullPath' => $tempFilePath
			]);
			jsonOutput([
				'success' => true,
				'newFileName' => $newName
			]);
		}
	}
}