//go:build darwin

#import "mpmediabridge.h"

/**
 * C bridge registering callbacks for media playback events using the native CommandCenter API.
 */
void register_os_remote_commands() {
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    [commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        os_remote_command_callback(PLAY, 0);
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        os_remote_command_callback(PAUSE, 0);
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.togglePlayPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        os_remote_command_callback(TOGGLE, 0);
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.stopCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        os_remote_command_callback(STOP, 0);
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.nextTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        os_remote_command_callback(NEXT_TRACK, 0);
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.previousTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        os_remote_command_callback(PREVIOUS_TRACK, 0);
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.changePlaybackPositionCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        MPChangePlaybackPositionCommandEvent *positionChangeEvent = (MPChangePlaybackPositionCommandEvent *)event;
        os_remote_command_callback(SEEK, positionChangeEvent.positionTime);
        return MPRemoteCommandHandlerStatusSuccess;
    }];
}

/**
 * C bridge setting "Now Playing" information on macOS for media playback using the native APIs.
 */
void set_os_now_playing_info(const char *title, const char *artist, const char *coverArtFileURL, double trackDuration) {
    NSString *coverArtLocationString = [NSString stringWithUTF8String:coverArtFileURL];
    NSURL *coverArtURL = [NSURL URLWithString:coverArtLocationString];
    NSImage *coverArtImage = [[NSImage alloc] initWithContentsOfURL:coverArtURL];

    MPMediaItemArtwork *coverArt = [[MPMediaItemArtwork alloc] initWithBoundsSize:coverArtImage.size requestHandler:^NSImage * _Nonnull(CGSize size) {
        return coverArtImage;
    }];

    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    NSDictionary *nowPlayingInfo = @{
        MPMediaItemPropertyTitle: [NSString stringWithUTF8String:title],
        MPMediaItemPropertyArtist: [NSString stringWithUTF8String:artist],
        MPMediaItemPropertyArtwork: coverArt,
        MPNowPlayingInfoPropertyElapsedPlaybackTime: @(0),
        MPMediaItemPropertyPlaybackDuration: @(trackDuration) // Expects 'NSNumber'
    };
    
    infoCenter.nowPlayingInfo = nowPlayingInfo;
}

/**
 * C bridge updating the OS playback position.
 * creates a mutable copy of the immutable dictionary and writes it back with updated position.
 */
void update_os_now_playing_info_position(double positionSeconds) {
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    NSMutableDictionary *updatedInfo = [infoCenter.nowPlayingInfo mutableCopy];
    updatedInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(positionSeconds);
    infoCenter.nowPlayingInfo = [updatedInfo copy];
}

/**
 * C bridge setting the OS playback state to 'playing'.
 */
void set_os_playback_state_playing() {
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    infoCenter.playbackState = MPNowPlayingPlaybackStatePlaying;
}

/**
 * C bridge setting the OS playback state to 'paused'.
 */
void set_os_playback_state_paused() {
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    infoCenter.playbackState = MPNowPlayingPlaybackStatePaused;
}

/**
 * C bridge setting the OS playback state to 'stopped'.
 */
void set_os_playback_state_stopped() {
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    infoCenter.playbackState = MPNowPlayingPlaybackStateStopped;
}
