<?php
/**
 * Description: Execute functions of api2convert.com server.
 * Documentation : https://www.api2convert.com/documentation
 *
 * @package     midi-Synth
 * @category    module
 * @author      Oleg Klenitsky
 * @copyright   2024 Oleg Klenitsky
 * @license     GPL-2.0-or-later
 */

if ( ! defined( "ABSPATH" ) ) {
	exit();
}

/**
 * Create a JOB
 */
function midiSynth_createJob(string $_masterAPIkey, string $conversionData){
  $curloptUrl = 'https://api.api2convert.com/v2/jobs';

  $curl = curl_init();

  curl_setopt_array(
    $curl,
    [
      CURLOPT_VERBOSE        => true, // this line is for debugging only
      CURLOPT_URL            => $curloptUrl,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_ENCODING       => "",
      CURLOPT_MAXREDIRS      => 10,
      CURLOPT_TIMEOUT        => 60,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
      CURLOPT_CUSTOMREQUEST  => "POST",
      CURLOPT_POSTFIELDS     => $conversionData,
      CURLOPT_HTTPHEADER     => [
        'x-oc-api-key: ' . $_masterAPIkey,
        'Content-Type: application/json',
      ],
    ]
  );

  $response = curl_exec($curl);

  // Check for cURL errors
  if (curl_errno($curl)) {
    echo esc_html("cURL Error: " . curl_error($curl));
  }

  curl_close($curl);

  return $response;
}

/**
 * UPLOAD a local file
 */
function midiSynth_fileUpload(string $_masterAPIkey, string $server, string $jobId, $file){

  $curloptUrl = $server . '/upload-file/' . $jobId;

  $curl = curl_init();

  curl_setopt_array(
    $curl,
    [
      CURLOPT_VERBOSE        => true, // this line is for debugging only
      CURLOPT_URL            => $curloptUrl,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_ENCODING       => '',
      CURLOPT_MAXREDIRS      => 10,
      CURLOPT_TIMEOUT        => 60,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
      CURLOPT_CUSTOMREQUEST  => 'POST',
      CURLOPT_POSTFIELDS     => [
          'file' => new CURLFILE($file)
      ],
      CURLOPT_HTTPHEADER     => [
          'x-oc-api-key: ' . $_masterAPIkey,
          'x-oc-upload-uuid: ' . wp_rand(0, 1000),
      ],
    ]);

  $response = curl_exec($curl);

  // Check for cURL errors
  if (curl_errno($curl)) {
    echo esc_html("cURL Error: " . curl_error($curl));
  }

  curl_close($curl);

  return $response;
}

function midiSynth_getJobInfo(string $_masterAPIkey, string $jobId){
  $curloptUrl = 'https://api.api2convert.com/v2/jobs/' . $jobId;

  $curl = curl_init();

  curl_setopt_array(
    $curl,
    [
      CURLOPT_VERBOSE        => true, // this line is for debugging only
      CURLOPT_URL            => $curloptUrl,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_ENCODING       => '',
      CURLOPT_MAXREDIRS      => 10,
      CURLOPT_TIMEOUT        => 60,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
      CURLOPT_CUSTOMREQUEST  => 'GET',
      CURLOPT_HTTPHEADER     => [
          'x-oc-api-key: ' . $_masterAPIkey,
      ],
    ]);

  $response = curl_exec($curl);

  // Check for cURL errors
  if (curl_errno($curl)) {
    echo esc_html("cURL Error: " . curl_error($curl));
  }

  curl_close($curl);

  return $response;
}

function midiSynth_convert(
	$_masterAPIkey,
	$_fileMidi,
	$_fileName,
	$_fileSize,
	$_formatAudio,
	$_modeAudio,
	$_codecAudio,
	$_frequencyAudio,
  $_resolutionAudio,
  $_bitrateAudio){

	if("mp3" == $_formatAudio || "aac" == $_formatAudio){
		$conversionData = sprintf(
		'{
			"conversion": [{
			    "category": "audio",
			    "target": "%s",
			    "options": {
			    		"channels": "%s",
			        "frequency": %d,
			        "audio_bitrate": %d,
			        "output_filename": "%s"
			    }
			}]
		}',$_formatAudio,$_modeAudio,$_frequencyAudio,$_bitrateAudio,$_fileName);
	}
	if("wav" == $_formatAudio || "flac" == $_formatAudio){
		$conversionData = sprintf(
		'{
			"conversion": [{
			    "category": "audio",
			    "target": "%s",
			    "options": {
			    		"channels": "%s",
			        "frequency": %d,
			        "audio_bitdepth": %d,
			        "output_filename": "%s"
			    }
			}]
		}',$_formatAudio,$_modeAudio,$_frequencyAudio,$_resolutionAudio,$_fileName);
	}

	if("wma" == $_formatAudio || "m4a" == $_formatAudio){
		$conversionData = sprintf(
		'{
			"conversion": [{
			    "category": "audio",
			    "target": "%s",
			    "options": {
			    		"channels": "%s",
			    		"audio_codec": "%s",
			        "frequency": %d,
			        "audio_bitrate": %d,
			        "output_filename": "%s"
			    }
			}]
		}',$_formatAudio,$_modeAudio,$_codecAudio,$_frequencyAudio,$_bitrateAudio,$_fileName);
	}

	echo("<b>STEP 2: Create Job:</b>");

	$responseAsJson  = midiSynth_createJob($_masterAPIkey, $conversionData);
	$responseAsArray = json_decode($responseAsJson, true);

	if(!empty($responseAsArray["errors"])){
		wp_die("<br>".esc_html("error: ".$responseAsArray["errors"]));
	}

	if(isset($responseAsArray["created_at"])){
		echo "<br>".esc_html("time: ".$responseAsArray["created_at"]);
	}else{
		wp_die("<br>no response");
	}

	$jobId = "";
	if(isset($responseAsArray["id"])){
		$jobId = $responseAsArray["id"];
		echo "<br>".esc_html("jobId: ".$jobId);
	}else{
		wp_die("<br>jobId not defined");
	}

	$uploadServer = "";
	if(isset($responseAsArray["server"])){
		$uploadServer = $responseAsArray["server"];
		echo "<br>".esc_html("upload server: ".$uploadServer);
	}else{
		wp_die("<br>uploadServer not defined");
	}

	echo ("<br><b>STEP 3: Create audio file:</b>");

	if($_formatAudio) echo "<br>".esc_html("format: ".$_formatAudio);
	if($_modeAudio) echo "<br>".esc_html("mode: ".$_modeAudio);
	if($_codecAudio) echo "<br>".esc_html("codec: ".$_codecAudio);
	if($_frequencyAudio) echo "<br>".esc_html("frequency: ".$_frequencyAudio." Hz");
	if($_resolutionAudio) echo "<br>".esc_html("resolution: ".$_resolutionAudio." Bit");
	if($_bitrateAudio) echo "<br>".esc_html("bitrate: ".$_bitrateAudio." kb/sec");

	$path = plugin_dir_path( __FILE__ );
	$dir  = $path ."tmp/";
	$file = $dir . $_fileName;

	$responseAsJson = midiSynth_fileUpload(
    $_masterAPIkey,
    $uploadServer,
    $jobId,
    $file
	);

	$responseAsArray = json_decode($responseAsJson, true);

	if(isset($responseAsArray["error"]) && "" !== $responseAsArray["error"]){
		wp_die (esc_html("<br>error: ".$responseAsArray["error"]));
	}
	if(isset($responseAsArray["completed"]) && true === $responseAsArray["completed"]){
		echo "<br>".esc_html("status: completed");
	}

	echo ("<br><b>STEP 4: Response from Job:</b>");

	if($_fileSize > 1 && $_fileSize < 10000) sleep(5);
	if($_fileSize > 10000 && $_fileSize < 50000) sleep(10);
	if($_fileSize > 50000 && $_fileSize < 100000) sleep(15);
	if($_fileSize > 100000 && $_fileSize < 120000) sleep(25);
	if($_fileSize > 120000 && $_fileSize < 150000) sleep(40);

	$jobStatus = true;
	while($jobStatus) {
		$responseAsJson = midiSynth_getJobInfo(
			$_masterAPIkey,
			$jobId
		);

    $responseAsArray = json_decode($responseAsJson, true);
    $cur_jobStatus = $responseAsArray['status']['code'];

    if("processing" == $cur_jobStatus)$jobStatus = true;
    if("completed" == $cur_jobStatus)$jobStatus = false;
    if("failed" == $cur_jobStatus)$jobStatus = false;

    sleep(20);
	}

	$responseAsJson = midiSynth_getJobInfo(
	  $_masterAPIkey,
	  $jobId
	);

	$responseAsArray = json_decode($responseAsJson, true);
	echo "<br>".esc_html("time:".$responseAsArray["modified_at"]);
	echo "<br>".esc_html("status: ".$responseAsArray["status"]["code"]);

	$download = (isset($responseAsArray['output'][0])) ?$responseAsArray['output'][0]['uri'] :"";

	$allowed_html = array(
		"a" => array(
				"class" => true,
				"href"  => true,
				"title" => true,
				"download" => true,
		),
		"br" => array(),
	);

	if("" !== $download) echo wp_kses("<br><a class='download' href=$download download>download file</a>", $allowed_html);
}

/**
* Validate masterAPIkey for convert.
*
* @return string.
*/
function midiSynth_validate_masterAPIkey($masterAPIkey){
	return trim(stripslashes($masterAPIkey));
}
/**
* Validate audio fileName for convert.
*
* @return string.
*/
function midiSynth_validate_fileName($fileName){
	$fileName = sanitize_file_name($fileName);
	$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));

	if ($extension === "mid" || $extension === "midi"){
		return $fileName;
	}else{
		wp_die(esc_html("file extension is incorrect: ".$extension));
	}
}
/**
* Validate audio fileSize for convert.
*
* @return string.
*/
function midiSynth_validate_fileSize($fileSize){
	return $fileSize;
}
/**
* Validate audio fileMidi for convert.
*
* @return base-64 format.
*/
function midiSynth_validate_fileMidi($fileMidi){
	//Checking MThd (Content)
	$content = base64_decode($fileMidi);
	$header = substr($content, 0, 4);

	if("MThd" == $header){
		return $fileMidi;
	}else{
		wp_die("Missing MThd header");
	}
}
/**
* Validate audio format of convert.
*
* @return string Command.
*/
function midiSynth_validate_formatAudio($formatAudio){
	$arr_format = ["mp3","wav","wma","m4a","aac","flac"];
	if( in_array($formatAudio, $arr_format) ){
		return $formatAudio;
	}else{
		wp_die(esc_html("failed format: ".$formatAudio));
	}
}
/**
* Validate audio mode of convert.
*
* @return string Command.
*/
function midiSynth_validate_modeAudio($modeAudio){
	$arr_mode = ["mono","stereo"];
	if( in_array($modeAudio, $arr_mode) ){
		return $modeAudio;
	}else{
		wp_die(esc_html("failed mode: ".$modeAudio));
	}
}
/**
* Validate audio codec of convert.
*
* @return string Command.
*/
function midiSynth_validate_codecAudio($codecAudio){
	$arr_codec = ["wma1","wma2","aac","alac","copy"];
	if( in_array($codecAudio, $arr_codec) ){
		return $codecAudio;
	}else{
		if("" !== $codecAudio)wp_die(esc_html("failed codec: ".$codecAudio));
	}
}
/**
* Validate audio frequency of convert.
*
* @return string Command.
*/
function midiSynth_validate_frequencyAudio($frequencyAudio){
	$arr_frequency = [8000,16000,24000,32000,48000,96000];
	if( in_array($frequencyAudio, $arr_frequency) ){
		return $frequencyAudio;
	}else{
		wp_die(esc_html("failed frequency: ".$frequencyAudio));
	}
}
/**
* Validate audio resolution of convert.
*
* @return string Command.
*/
function midiSynth_validate_resolutionAudio($resolutionAudio){
	$arr_resolution = [8,16,24,32];
	if( in_array($resolutionAudio, $arr_resolution) ){
		return $resolutionAudio;
	}else{
		if("" !== $resolutionAudio)wp_die(esc_html("failed resolution: ".$resolutionAudio));
	}
}
/**
* Validate audio bitrate of convert.
*
* @return string Command.
*/
function midiSynth_validate_bitrateAudio($bitrateAudio){
	$arr_bitrate = [24,48,96,128,192,256];
	if( in_array($bitrateAudio, $arr_bitrate) ){
		return $bitrateAudio;
	}else{
		if("" !== $bitrateAudio)wp_die(esc_html("failed bitrate: ".$bitrateAudio));
	}
}
function midiSynth_export(){

	// security check.
	if(array_key_exists("nonce", $_POST)){
		$_midiSynth_nonce = filter_input( INPUT_POST, "nonce", FILTER_DEFAULT );
		if ( false === wp_verify_nonce( $_midiSynth_nonce, 'midiSynth' ) ) {
			wp_die( 'Security check failed!' );
    }
	}else{
		wp_die( "midiSynth: nonce missing." );
	}
	if( $_midiSynth_nonce !== wp_create_nonce( "midiSynth" ) ){
		wp_die( "midiSynth: nonce is incorrect." );
	}

	$_masterAPIkey = "";
	if(array_key_exists("masterAPIkey", $_POST)){
		$_masterAPIkey = filter_input(INPUT_POST, "masterAPIkey", FILTER_CALLBACK, array("options"=>"midiSynth_validate_masterAPIkey"));
	}

	$_fileName = "";
	if(array_key_exists("fileName", $_POST)){
		$_fileName = filter_input(INPUT_POST, "fileName", FILTER_CALLBACK, array("options"=>"midiSynth_validate_fileName"));
	}

	$_fileSize = "";
	if(array_key_exists("fileSize", $_POST)){
		$_fileSize = filter_input(INPUT_POST, "fileSize", FILTER_CALLBACK, array("options"=>"midiSynth_validate_fileSize"));
	}

	$_fileMidi = "";
	if(array_key_exists("fileMidi", $_POST)){
		$_fileMidi = filter_input(INPUT_POST, "fileMidi", FILTER_CALLBACK, array("options"=>"midiSynth_validate_fileMidi"));
	}

	$_formatAudio = "";
	if(array_key_exists("formatAudio", $_POST)){
		$_formatAudio = filter_input(INPUT_POST, "formatAudio", FILTER_CALLBACK, array("options"=>"midiSynth_validate_formatAudio"));
	}

	$_modeAudio = "";
	if (array_key_exists("modeAudio", $_POST)){
		$_modeAudio = filter_input(INPUT_POST, "modeAudio", FILTER_CALLBACK, array("options"=>"midiSynth_validate_modeAudio"));
	}

	$_codecAudio = "";
	if (array_key_exists("codecAudio", $_POST)){
		$_codecAudio = filter_input(INPUT_POST, "codecAudio", FILTER_CALLBACK, array("options"=>"midiSynth_validate_codecAudio"));
	}

	$_frequencyAudio = "";
	if(array_key_exists("frequencyAudio", $_POST)){
		$_frequencyAudio = filter_input(INPUT_POST, "frequencyAudio", FILTER_CALLBACK, array("options"=>"midiSynth_validate_frequencyAudio"));
	}

	$_resolutionAudio = "";
	if(array_key_exists("resolutionAudio", $_POST)){
		$_resolutionAudio = filter_input(INPUT_POST, "resolutionAudio", FILTER_CALLBACK, array("options"=>"midiSynth_validate_resolutionAudio"));
	}

	$_bitrateAudio = "";
	if(array_key_exists("bitrateAudio", $_POST)){
		$_bitrateAudio = filter_input(INPUT_POST, "bitrateAudio", FILTER_CALLBACK, array("options"=>"midiSynth_validate_bitrateAudio"));
	}

	WP_Filesystem();
	global $wp_filesystem;

	$path = plugin_dir_path( __FILE__ );
	$dir  = $path ."tmp/";

	$content = base64_decode($_fileMidi);

	$fileName = $dir . $_fileName;
	$wp_filesystem->put_contents( $fileName, $content, FS_CHMOD_FILE );

	midiSynth_convert(
		$_masterAPIkey,
		$_fileMidi,
		$_fileName,
		$_fileSize,
		$_formatAudio,
		$_modeAudio,
		$_codecAudio,
		$_frequencyAudio,
	  $_resolutionAudio,
		$_bitrateAudio);

	//Delete uploaded midi file from /tmp directory
	$wp_filesystem->delete($fileName);

	wp_die();
}
