//
//  DdbPlayItemPasteboardSerializer.m
//  DeaDBeeF
//
//  Created by Oleksiy Yakovenko on 8/28/20.
//  Copyright © 2020 Oleksiy Yakovenko. All rights reserved.
//

#import "DdbPlayItemPasteboardSerializer.h"
#import "DdbShared.h"

extern DB_functions_t *deadbeef;

@interface DdbPlayItemPasteboardSerializer()

@property (nonatomic) ddb_playItem_t **items;
@property (nonatomic) NSInteger count;

@end

@implementation DdbPlayItemPasteboardSerializer

// NSSecureCoding
@dynamic supportsSecureCoding;
+ (BOOL) supportsSecureCoding {
    return YES;
}

- (instancetype)init {
    return [self initWithItem:nil];
}

- (instancetype)initWithItem:(ddb_playItem_t *)item {
    if (item == NULL) {
        return [self initWithItems:NULL count:0];
    }
    return [self initWithItems:&item count:1];
}

- (instancetype)initWithItems:(ddb_playItem_t * _Nonnull *)items count:(NSInteger)count {
    self = [super init];
    if (!self) {
        return nil;
    }


    if (count == 0) {
        return self;
    }

    _items = calloc(count, sizeof (ddb_playItem_t *));
    for (NSInteger i = 0; i < count; i++) {
        _items[i] = deadbeef->pl_item_alloc();
        deadbeef->pl_item_copy(_items[i], items[i]);
    }
    _count = count;

    return self;
}

- (void)dealloc {
    for (NSInteger i = 0; i < _count; i++) {
        deadbeef->pl_item_unref(_items[i]);
    }
    _count = 0;
    free (_items);
    _items = NULL;
}

// NSCoding

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [self initWithItem:nil];
    if (!self) {
        return nil;
    }

    NSData *data = [aDecoder decodeObjectOfClass:NSArray.class forKey:@"DdbPlaylistData"];
    if (data == nil) {
        return self;
    }

    ddb_playlist_t *plt = deadbeef->plt_alloc("clipboard");
    int res = deadbeef->plt_load_from_buffer (plt, data.bytes, data.length);
    if (res == 0) {
        size_t count = deadbeef->plt_get_items(plt, &_items);
        _count = (NSInteger)count;
    }

    deadbeef->plt_unref (plt);

    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    if (_count == 0) {
        return;
    }

    ddb_playlist_t *plt = deadbeef->plt_alloc("clipboard");

    ddb_playItem_t *after = NULL;
    for (NSInteger i = 0; i < _count; i++) {
        after = deadbeef->plt_insert_item(plt, after, _items[i]);
    }

    uint8_t *buffer = NULL;
    ssize_t size = deadbeef->plt_save_to_buffer (plt, &buffer);

    deadbeef->plt_unref (plt);
    plt = NULL;

    if (size == 0) {
        return;
    }
    NSData *data = [NSData dataWithBytes:buffer length:size];
    free (buffer);

    [aCoder encodeObject:data forKey:@"DdbPlaylistData"];
}



// NSPasteboardReading
+ (nonnull NSArray<NSPasteboardType> *)readableTypesForPasteboard:(nonnull NSPasteboard *)pasteboard {
    return @[ddbPlaylistDataUTIType];
}

+ (NSPasteboardReadingOptions)readingOptionsForType:(NSPasteboardType)type pasteboard:(NSPasteboard *)pasteboard {
    return NSPasteboardReadingAsKeyedArchive;
}

// NSPasteboardWriting
- (NSArray<NSString *> *)writableTypesForPasteboard:(NSPasteboard *)pasteboard {
    return @[ddbPlaylistDataUTIType];
}

- (id)pasteboardPropertyListForType:(NSString *)type {
    if( [type isEqualToString:ddbPlaylistDataUTIType] ) {
#ifdef MAC_OS_X_VERSION_10_14
        if (@available(macOS 10.13, *)) {
            return [NSKeyedArchiver archivedDataWithRootObject:self requiringSecureCoding:NO error:nil];
        }
        else
#endif
        {
            return [NSKeyedArchiver archivedDataWithRootObject:self];
        }
    }

    return nil;
}


@end
