#import "PictureInPictureManager.h"
#import "../VeLivePlayerMultiObserver.h"
#import <AVKit/AVKit.h>
#import <TTSDKFramework/TTVideoLive.h>
#import <UIKit/UIKit.h>
#import <VolcApiEngine/VePictureInPictureController.h>
#import <VolcApiEngine/VePictureInPictureDefine.h>

@protocol VeLivePlayerObserver;
@protocol VePictureInPictureDelegate;
@protocol VeLivePictureInPictureManagerListener;

// Add class extension to declare private properties instead of redefining
// interface
@interface VeLivePictureInPictureManager () <
    VeLivePlayerObserver, VePictureInPictureDelegate,
    VeLivePictureInPictureManagerListener>
@property(nonatomic, strong) VePictureInPictureController *pipController;
@property(nonatomic, assign) BOOL enableVideoObserver;
@property(nonatomic, strong) TVLManager *player;
@property(nonatomic, weak) UIView *contentView;
@property(nonatomic, weak) id<VeLivePictureInPictureManagerListener> listener;
@property(nonatomic, assign) BOOL pipAutoStart;
@property(nonatomic, strong)
    NSMutableDictionary<NSString *, void (^)(AVPictureInPictureController *)>
        *pipObservers;
// Add timer to refresh playback state
@property(nonatomic, strong) NSTimer *playbackStateTimer;
@end

NSString *const kObserverKey = @"pip-observer";

@implementation VeLivePictureInPictureManager

+ (instancetype)sharedInstance {
  static VeLivePictureInPictureManager *instance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    instance = [[self alloc] init];
  });
  return instance;
}

+ (instancetype)getInstance {
  return [self sharedInstance];
}

- (instancetype)init {
  if (self = [super init]) {
    _autoHideViewController = YES;
    _pipObservers = [NSMutableDictionary dictionary];
    if (@available(iOS 14.2, *)) {
      _canStartPictureInPictureAutomaticallyFromInline = NO;
    }
  }
  return self;
}

- (void)dealloc {
  [self disableVideoFrameObserver];
  [self stopPlaybackStateTimer];

  if (self.pipController) {
    self.pipController.delegate = nil;
    self.pipController = nil;
  }

  [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
}

// Start playback state refresh timer
- (void)startPlaybackStateTimer {
  [self stopPlaybackStateTimer];

  if (self.pipController && [self.pipController pictureInPictureController]) {
    // Use main thread timer to ensure UI updates on main thread
    self.playbackStateTimer = [NSTimer
        scheduledTimerWithTimeInterval:1.0
                                target:self
                              selector:@selector(invalidatePlaybackState)
                              userInfo:nil
                               repeats:YES];
    // Add timer to main run loop
    [[NSRunLoop mainRunLoop] addTimer:self.playbackStateTimer
                              forMode:NSRunLoopCommonModes];
    NSLog(@"PIP: Started playback state timer");
  }
}

// Stop playback state refresh timer
- (void)stopPlaybackStateTimer {
  if (self.playbackStateTimer) {
    [self.playbackStateTimer invalidate];
    self.playbackStateTimer = nil;
    NSLog(@"PIP: Stopped playback state timer");
  }
}

// Timer callback: refresh playback state
- (void)invalidatePlaybackState {
  if (self.pipController && [self.pipController pictureInPictureController]) {
    AVPictureInPictureController *controller =
        [self.pipController pictureInPictureController];
    if (controller.isPictureInPictureActive) {
      [controller invalidatePlaybackState];
    }
  }
}

- (void)setupPlayer:(TVLManager *)player {
  [self ensurePipControllerReady:player completion:nil];
}

- (void)ensurePipControllerReady:(TVLManager *)player
                      completion:(nullable void (^)(void))completion {
  if (player && self.player != player) {
    if (self.player) {
      [self disableVideoFrameObserver];
    }
    self.player = player;
    self.contentView = player.playerView;
  }

  if (!self.pipController) {
    [self initPipController];
    [self enableVideoFrameObserver];
    [self updatePipController:completion];
  }

  if (self.contentView && self.pipController) {
    if (@available(iOS 14.2, *)) {
      self.pipController.canStartPictureInPictureAutomaticallyFromInline =
          self.canStartPictureInPictureAutomaticallyFromInline;
    }
    [self updatePipController:completion];
  } else {
    if (completion) {
      completion();
    }
  }
}

// Add a persistent observer for PIP controller status, returns observer ID
- (NSString *)addPipControllerObserver:
    (void (^)(AVPictureInPictureController *pipController))observer {
  if (!observer) {
    return nil;
  }

  NSString *observerId = [NSString
      stringWithFormat:@"observer_%@_%lu", [[NSUUID UUID] UUIDString],
                       (unsigned long)[NSDate date].timeIntervalSince1970];

  self.pipObservers[observerId] = observer;

  // If PIP controller is already ready, notify immediately
  if (self.pipController) {
    observer([self.pipController pictureInPictureController]);
  }

  return observerId;
}

// Remove observer by ID
- (void)removePipControllerObserver:(NSString *)observerId {
  if (observerId) {
    [self.pipObservers removeObjectForKey:observerId];
  }
}

// Remove all observers
- (void)removeAllPipControllerObservers {
  [self.pipObservers removeAllObjects];
}

- (void)initPipController {
  if (self.pipController != nil) {
    self.pipController.delegate = nil;
    self.pipController = nil;
  }
  self.pipController = [[VePictureInPictureController alloc]
      initWithType:VePictureInPictureTypeContentSource
       contentView:self.player.playerView];
  [self.pipController setRenderMode:1];
  self.pipController.delegate = self;
  self.pipController.autoConfigAudioSession = YES;
  if (@available(iOS 14.2, *)) {
    self.pipController.canStartPictureInPictureAutomaticallyFromInline =
        self.canStartPictureInPictureAutomaticallyFromInline;
  }
  if (@available(iOS 14.0, *)) {
    self.pipController.requiresLinearPlayback = NO;
  }

  if (self.pipObservers.count > 0) {
    dispatch_async(dispatch_get_main_queue(), ^{
      [self notifyPipControllerReady];
    });
  }
}

- (void)updatePipController:(nullable void (^)(void))completion {
  VeLivePlayerVideoStreamInfo *info = [self.player getVideoStreamInfo];

  if (!CGSizeEqualToSize(CGSizeZero, CGSizeMake(info.width, info.height))) {
    [self.pipController setVideoSize:CGSizeMake(info.width, info.height)
                          completion:nil];
  }

  [self.pipController setContentView:self.contentView
                          completion:^{
                            if (completion) {
                              completion();
                            }
                          }];
}

// Notify all observers
- (void)notifyPipControllerReady {
  if (!self.pipController) {
    return;
  }

  AVPictureInPictureController *controller =
      [self.pipController pictureInPictureController];

  // copy observers to avoid modifying the dictionary while iterating
  NSDictionary *observersCopy = [self.pipObservers copy];

  // Notify all persistent observers
  for (void (^observer)(AVPictureInPictureController *)
           in observersCopy.allValues) {
    if (observer) {
      observer(controller);
    }
  }
}

- (void)enableVideoFrameObserver {
  if (self.enableVideoObserver) {
    // If already enabled, disable then re-enable to ensure the observer is
    // re-registered
    [self disableVideoFrameObserver];
  }
  self.enableVideoObserver = YES;
  [self.player
      enableVideoFrameObserver:YES
                   pixelFormat:VeLivePlayerPixelFormatBGRA32
                    bufferType:VeLivePlayerVideoBufferTypeSampleBuffer];
  [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
  [[VeLivePlayerMultiObserver sharedInstance] addObserver:kObserverKey
                                                 observer:self];
}

- (void)disableVideoFrameObserver {
  if (!self.enableVideoObserver) {
    return;
  }
  self.enableVideoObserver = NO;
  [self.player enableVideoFrameObserver:NO
                            pixelFormat:VeLivePlayerPixelFormatUnknown
                             bufferType:VeLivePlayerVideoBufferTypeUnknown];
  [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
}

- (void)startPictureInPicture {
  if (!self.player) {
    return;
  }

  [self ensurePipControllerReady:self.player
                      completion:^{
                        if (@available(iOS 14.0, *)) {
                          [self.player setSupportPictureInPictureMode:YES];
                          BOOL startSuccess =
                              [self.pipController startPictureInPicture];
                          if (!startSuccess) {
                            NSLog(@"PIP: Failed to start picture-in-picture");
                          }
                        }
                      }];
}

- (void)stopPictureInPicture {
  if (self.autoHideViewController) {
    [self.pipController
        stopPictureInPictureWithType:VePictureInPictureStopTypeFromApiRestore];
  } else {
    [self.pipController stopPictureInPicture];
  }
}

- (void)destroyPictureInPicture {
  dispatch_async(dispatch_get_main_queue(), ^{
    [self stopPictureInPicture];

    // ensure this is called on the main thread
    [self disableVideoFrameObserver];

    // clear delegate to avoid retain cycle
    if (self.pipController) {
      self.pipController.delegate = nil;
    }

    self.pipController = nil;

    if (@available(iOS 14.2, *)) {
      [self setCanStartPictureInPictureAutomaticallyFromInline:NO];
    }
  });
}

- (BOOL)isPictureInPictureStarted {
  return [VePictureInPictureController isPictureInPictureStarted];
}

- (BOOL)isPictureInPictureSupported {
  return [VePictureInPictureController isPictureInPictureSupported];
}

- (void)enablePictureInPicture {
  _canStartPictureInPictureAutomaticallyFromInline = YES;
  if (self.pipController != nil) {
    if (@available(iOS 14.2, *)) {
      self.pipController.canStartPictureInPictureAutomaticallyFromInline = YES;
    }
  }
  dispatch_async(dispatch_get_main_queue(), ^{
    if (@available(iOS 14.2, *)) {
      [self ensurePipControllerReady:self.player completion:nil];
    }
  });
}

- (void)disablePictureInPicture {
  _canStartPictureInPictureAutomaticallyFromInline = NO;
  if (self.pipController != nil) {
    self.pipController.canStartPictureInPictureAutomaticallyFromInline = NO;
  }
  dispatch_async(dispatch_get_main_queue(), ^{
    if (@available(iOS 14.2, *)) {
      [self destroyPictureInPicture];
    }
  });
}

- (void)setListener:(id<VeLivePictureInPictureManagerListener>)listener {
  _listener = listener;
}

#pragma mark - AVPictureInPictureSampleBufferPlaybackDelegate
- (BOOL)pictureInPictureControllerIsPlaybackPaused:
    (nonnull AVPictureInPictureController *)pictureInPictureController {
  if (self.player) {
    return ![[self.player valueForKey:@"isPlaying"] boolValue];
  }
  NSLog(@"PIP: No player, returning YES (paused)");
  return YES;
}

- (void)pictureInPictureController:
            (AVPictureInPictureController *)pictureInPictureController
                        setPlaying:(BOOL)playing {
  if (playing) {
    [self.player play];
  } else {
    [self.player pause];
  }
}

// MARK: - VeLiveVideoFrameListener
- (void)onRenderVideoFrame:(TVLManager *_Nonnull)player
                videoFrame:(VeLivePlayerVideoFrame *_Nonnull)videoFrame {
  @autoreleasepool {
    // Ensure pipController exists and is valid, avoid processing buffer during
    // destruction
    if (!self.pipController || !self.enableVideoObserver) {
      return;
    }

    if (@available(iOS 15.0, *)) {
      if (videoFrame.bufferType == VeLivePlayerVideoBufferTypePixelBuffer) {
        CVPixelBufferRef pixelBuffer = videoFrame.pixelBuffer;
        if (pixelBuffer != NULL) {
          [self.pipController enqueuePixelBuffer:pixelBuffer];
        }
      } else if (videoFrame.bufferType ==
                 VeLivePlayerVideoBufferTypeSampleBuffer) {
        CMSampleBufferRef sampleBuffer = videoFrame.sampleBuffer;
        if (sampleBuffer != NULL) {
          [self.pipController enqueueSampleBuffer:sampleBuffer];
        }
      }
    }
  }
}

- (void)onError:(TVLManager *)player error:(VeLivePlayerError *)error {
  NSLog(@"VeLiveQuickStartDemo: Error %ld, %@", error.code, error.errorMsg);
}

// MARK: - VeLivePlayerObserver
- (void)onPlayerStatusUpdate:(TVLManager *)player status:(NSInteger)status {
  // Refresh picture-in-picture playback state when player status changes
  if (self.pipController && [self.pipController pictureInPictureController]) {
    [[self.pipController pictureInPictureController] invalidatePlaybackState];
  }
  NSLog(@"PIP: Player status updated to %ld, invalidated playback state",
        (long)status);
}

/// MARK: - VePictureInPictureDelegate
- (void)pictureInPictureController:
            (VePictureInPictureController *)pictureInPictureController
                     statusChanged:(VePictureInPictureStatus)fromStatus
                                to:(VePictureInPictureStatus)toStatus {
  switch (toStatus) {
  case VePictureInPictureStatusIde: {

  } break;
  case VePictureInPictureStatusPreparing: {

  } break;
  case VePictureInPictureStatusReady: {
    [self notifyPipControllerReady];
  } break;
  case VePictureInPictureStatusWillStart: {

  } break;
  case VePictureInPictureStatusDidStart: {
    if (self.listener) {
      [self.listener onStartPictureInPicture];
    }
    // Start timer to refresh playback state
    [self startPlaybackStateTimer];
    break;
  case VePictureInPictureStatusWillChange: {

  } break;
  case VePictureInPictureStatusDidChange: {

  } break;
  case VePictureInPictureStatusRestoreUI: {

  } break;
  case VePictureInPictureStatusWillStop: {

  } break;
  case VePictureInPictureStatusDidStop: {
    if (self.listener) {
      [self.listener onStopPictureInPicture];
    }
    // Stop timer
    [self stopPlaybackStateTimer];
    if (@available(iOS 14.2, *)) {
      if (!self.canStartPictureInPictureAutomaticallyFromInline) {
        [self destroyPictureInPicture];
      }
    }
  } break;
  case VePictureInPictureStatusError: {
    if (self.listener) {
      [self.listener onError:pictureInPictureController.error.code
                   extraData:pictureInPictureController.error.userInfo];
    }
    // Stop timer
    [self stopPlaybackStateTimer];
  } break;
  }
  }
}

@end
