# Copyright (C) Innuos
# SPDX-License-Identifier: GPL-2.0

package Plugins::MQALink::ProtocolHandler;

# Handler for mqalink:// URLs

use strict;
use base qw(Slim::Player::Protocols::File);
use Slim::Utils::Log;
use Slim::Utils::Misc;
use Slim::Utils::Prefs;

use File::Spec::Functions qw(catdir);
use IO::String;

use Data::Dumper;
use JSON::XS::VersionOneAndTwo;


use Slim::Music::Info;
use Slim::Utils::Log;
use Slim::Utils::Misc;
use Slim::Utils::Prefs;
use Slim::Formats;
use Slim::Player::Source;
use URI::Escape qw(uri_escape_utf8 uri_unescape);

my $log   = logger('plugin.mqalink');
my $prefs = preferences('plugin.mqalink');

my %url_to_duration;

use constant INNUOS_API_URL => "http://localhost:8090/api/track_details/get_stream_url";


sub canSeek { 1 }
sub canTranscodeSeek { 1 }
sub isRemote { 0 }
sub canSkip { 1 }
sub canDirectStream { 0 }

sub new {
	my $class = shift;
	my $args  = shift;

	if (!$args->{'song'}) {
		logWarning("No song passed!");
		return undef;
	}

	logWarning("New Song: " . $args->{'song'});
	main::DEBUGLOG && $log->is_debug && $log->debug( "New Song: " . $args->{'song'});


	my $self = $class->open($args);

	if (defined($self)) {
		${*$self}{'song'}        = $args->{'song'};
		${*$self}{'client'}      = $args->{'client'};
		${*$self}{'contentType'} = 'mqa';

		${*$self}{'handler'} = $class;
	}

	return $self;
}

sub open {
	my $class = shift;
	my $args  = shift;



	my $song     = $args->{'song'};
	my $track    = $song->currentTrack();
	my $url      = $class->standardPathFromFileURL($track->url);
	my $client   = $args->{'client'};

	#%Slim::Music::Info::setContentType($track->url, 'mqa');
	# $track->url($url);
	# Slim::Music::Info::setDuration($track->url, '120');

	main::DEBUGLOG && $log->is_debug && $log->debug( 'Track duration' . $song->duration );
	main::DEBUGLOG && $log->is_debug && $log->debug( 'Song info duration' . Slim::Music::Info::setDuration($track->url, '120') );

	#$song->streamUrl($class->pathFromFileURL($url));

	my $sock = $class->SUPER::open( $args ) || return;

	return $sock;
}

sub getMetadataFor {

	my ( $class, $client, $url ) = @_;

	my $duration = 0;

	if (exists($url_to_duration{$url})) {
		$duration = $url_to_duration{$url};
	}

	my $meta = {
		artist     => 'Innuos',
		album      => 'Music Server',
		title      => 'Playing MQA',
		cover      => '',
		bitrate    => '',
		samplerate => '',
		samplesize => '',
		type       => '',
		duration   => $duration,
	};

	main::DEBUGLOG && $log->is_debug && $log->debug( 'Get metadata: ' . $meta );


	return $meta;
}

sub standardPathFromFileURL {
	# remove the initial mqalink:// to get just the path
	my $path = substr $_[1], 10;
	my $file_url = 'file://' . $path;
	return $file_url;
}

sub pathFromFileURL {
	my $original_url = $_[1];
	my $path;
	if ($original_url =~ m/^file/) {
		$path = substr $original_url, 7;
	} else {
		$path = substr $original_url, 10;
	}
	main::DEBUGLOG && $log->is_debug && $log->debug( 'Get path from URL 1: ' . $path );
	return $path;
}

sub getNextTrack {

	# Perform any operations, such as interaction with music services, to obtain all the necessary details of the
	# next track to be streamed. Like, scanUrl, the work of this method is performed asynchronously, the results being
	# notified by callbacks. This may determine that the stream URL will be different from the Track URL, and so may
	# also require a different handler.

	my ($class, $song, $successCb, $errorCb) = @_;
	# $song->duration('120');
	# $song->bitrate(649000);

	my $params = shift;
	my $path = $class->pathFromFileURL($song->currentTrack()->url);
	my $encoded = uri_escape_utf8( $path );
	my $apiURL = INNUOS_API_URL . "/" . $encoded;

	Slim::Networking::SimpleAsyncHTTP->new(
		# Upon successful call
		sub {
			my $response = shift;

			my $result = eval { from_json($response->content) };

			$@ && $log->error($@);

			main::DEBUGLOG && $log->is_debug  && $log->debug(Dumper($result));

			$song->duration($result->{duration});
			$song->bitrate($result->{bitrate});
			main::DEBUGLOG && $log->is_debug && $log->debug('Duration: ' . $song->duration);
			main::DEBUGLOG && $log->is_debug && $log->debug('Bitrate:' . $song->bitrate);
			$url_to_duration{$song->currentTrack()->url} = $result->{duration};

			$successCb->();
		},
		# Upon Error with call
		sub {
			my ($http, $error) = @_;

			my $errorCb = $params->{errorCb};

			main::DEBUGLOG && $log->is_debug  && $log->debug(Dumper($error));

			$errorCb->("Error getting track url from innuOS")
		},
		{
			timeout => 15,
		},
	)->get($apiURL);
}

sub getFormatForURL {
	return "mqa";
}


sub contentType {
	return 'mqa';
}

sub formatOverride {
	main::DEBUGLOG && $log->is_debug && $log->debug( 'Format Override' );
	return 'mqa';
}

1;
