/*
 *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#import "ARDSettingsViewController.h"
#import "ARDSettingsModel.h"
#import "RTCVideoCodecInfo+HumanReadable.h"

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(int, ARDSettingsSections) {
  ARDSettingsSectionAudioSettings = 0,
  ARDSettingsSectionVideoResolution,
  ARDSettingsSectionVideoCodec,
  ARDSettingsSectionBitRate,
};

typedef NS_ENUM(int, ARDAudioSettingsOptions) {
  ARDAudioSettingsAudioOnly = 0,
  ARDAudioSettingsCreateAecDump,
  ARDAudioSettingsUseManualAudioConfig,
};

@interface ARDSettingsViewController () <UITextFieldDelegate> {
  ARDSettingsModel *_settingsModel;
}

@end

@implementation ARDSettingsViewController

- (instancetype)initWithStyle:(UITableViewStyle)style
                settingsModel:(ARDSettingsModel *)settingsModel {
  self = [super initWithStyle:style];
  if (self) {
    _settingsModel = settingsModel;
  }
  return self;
}

#pragma mark - View lifecycle

- (void)viewDidLoad {
  [super viewDidLoad];
  self.title = @"Settings";
  [self addDoneBarButton];
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
}

#pragma mark - Data source

- (NSArray<NSString *> *)videoResolutionArray {
  return [_settingsModel availableVideoResolutions];
}

- (NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)videoCodecArray {
  return [_settingsModel availableVideoCodecs];
}

#pragma mark -

- (void)addDoneBarButton {
  UIBarButtonItem *barItem = [[UIBarButtonItem alloc]
      initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                           target:self
                           action:@selector(dismissModally:)];
  self.navigationItem.leftBarButtonItem = barItem;
}

#pragma mark - Dismissal of view controller

- (void)dismissModally:(id)sender {
  [self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  return 4;
}

- (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section {
  switch (section) {
    case ARDSettingsSectionAudioSettings:
      return 3;
    case ARDSettingsSectionVideoResolution:
      return self.videoResolutionArray.count;
    case ARDSettingsSectionVideoCodec:
      return self.videoCodecArray.count;
    default:
      return 1;
  }
}

#pragma mark - Table view delegate helpers

- (void)removeAllAccessories:(UITableView *)tableView inSection:(int)section {
  for (int i = 0; i < [tableView numberOfRowsInSection:section]; i++) {
    NSIndexPath *rowPath = [NSIndexPath indexPathForRow:i inSection:section];
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:rowPath];
    cell.accessoryType = UITableViewCellAccessoryNone;
  }
}

- (void)tableView:(UITableView *)tableView
    updateListSelectionAtIndexPath:(NSIndexPath *)indexPath
                         inSection:(int)section {
  [self removeAllAccessories:tableView inSection:section];
  UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
  cell.accessoryType = UITableViewCellAccessoryCheckmark;
  [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark - Table view delegate

- (nullable NSString *)tableView:(UITableView *)tableView
         titleForHeaderInSection:(NSInteger)section {
  switch (section) {
    case ARDSettingsSectionAudioSettings:
      return @"Audio";
    case ARDSettingsSectionVideoResolution:
      return @"Video resolution";
    case ARDSettingsSectionVideoCodec:
      return @"Video codec";
    case ARDSettingsSectionBitRate:
      return @"Maximum bitrate";
    default:
      return @"";
  }
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  switch (indexPath.section) {
    case ARDSettingsSectionAudioSettings:
      return [self audioSettingsTableViewCellForTableView:tableView
                                              atIndexPath:indexPath];

    case ARDSettingsSectionVideoResolution:
      return [self videoResolutionTableViewCellForTableView:tableView
                                                atIndexPath:indexPath];

    case ARDSettingsSectionVideoCodec:
      return [self videoCodecTableViewCellForTableView:tableView
                                           atIndexPath:indexPath];

    case ARDSettingsSectionBitRate:
      return [self bitrateTableViewCellForTableView:tableView
                                        atIndexPath:indexPath];

    default:
      return [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                    reuseIdentifier:@"identifier"];
  }
}

- (void)tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  switch (indexPath.section) {
    case ARDSettingsSectionVideoResolution:
      [self tableView:tableView disSelectVideoResolutionAtIndex:indexPath];
      break;

    case ARDSettingsSectionVideoCodec:
      [self tableView:tableView didSelectVideoCodecCellAtIndexPath:indexPath];
      break;
  }
}

#pragma mark - Table view delegate(Video Resolution)

- (UITableViewCell *)
    videoResolutionTableViewCellForTableView:(UITableView *)tableView
                                 atIndexPath:(NSIndexPath *)indexPath {
  NSString *dequeueIdentifier = @"ARDSettingsVideoResolutionViewCellIdentifier";
  UITableViewCell *cell =
      [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier];
  if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:dequeueIdentifier];
  }
  NSString *resolution = self.videoResolutionArray[indexPath.row];
  cell.textLabel.text = resolution;
  if ([resolution
          isEqualToString:[_settingsModel
                              currentVideoResolutionSettingFromStore]]) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
  } else {
    cell.accessoryType = UITableViewCellAccessoryNone;
  }

  return cell;
}

- (void)tableView:(UITableView *)tableView
    disSelectVideoResolutionAtIndex:(NSIndexPath *)indexPath {
  [self tableView:tableView
      updateListSelectionAtIndexPath:indexPath
                           inSection:ARDSettingsSectionVideoResolution];

  NSString *videoResolution = self.videoResolutionArray[indexPath.row];
  [_settingsModel storeVideoResolutionSetting:videoResolution];
}

#pragma mark - Table view delegate(Video Codec)

- (UITableViewCell *)
    videoCodecTableViewCellForTableView:(UITableView *)tableView
                            atIndexPath:(NSIndexPath *)indexPath {
  NSString *dequeueIdentifier = @"ARDSettingsVideoCodecCellIdentifier";
  UITableViewCell *cell =
      [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier];
  if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:dequeueIdentifier];
  }
  RTC_OBJC_TYPE(RTCVideoCodecInfo) *codec = self.videoCodecArray[indexPath.row];
  cell.textLabel.text = [codec humanReadableDescription];
  if ([codec isEqualToCodecInfo:[_settingsModel
                                    currentVideoCodecSettingFromStore]]) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
  } else {
    cell.accessoryType = UITableViewCellAccessoryNone;
  }

  return cell;
}

- (void)tableView:(UITableView *)tableView
    didSelectVideoCodecCellAtIndexPath:(NSIndexPath *)indexPath {
  [self tableView:tableView
      updateListSelectionAtIndexPath:indexPath
                           inSection:ARDSettingsSectionVideoCodec];

  RTC_OBJC_TYPE(RTCVideoCodecInfo) *videoCodec =
      self.videoCodecArray[indexPath.row];
  [_settingsModel storeVideoCodecSetting:videoCodec];
}

#pragma mark - Table view delegate(Bitrate)

- (UITableViewCell *)bitrateTableViewCellForTableView:(UITableView *)tableView
                                          atIndexPath:(NSIndexPath *)indexPath {
  NSString *dequeueIdentifier = @"ARDSettingsBitrateCellIdentifier";
  UITableViewCell *cell =
      [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier];
  if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:dequeueIdentifier];

    UITextField *textField = [[UITextField alloc]
        initWithFrame:CGRectMake(10,
                                 0,
                                 cell.bounds.size.width - 20,
                                 cell.bounds.size.height)];
    NSString *currentMaxBitrate =
        [_settingsModel currentMaxBitrateSettingFromStore].stringValue;
    textField.text = currentMaxBitrate;
    textField.placeholder = @"Enter max bit rate (kbps)";
    textField.keyboardType = UIKeyboardTypeNumberPad;
    textField.delegate = self;

    // Numerical keyboards have no return button, we need to add one manually.
    UIToolbar *numberToolbar = [[UIToolbar alloc]
        initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)];
    numberToolbar.items = @[
      [[UIBarButtonItem alloc]
          initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                               target:nil
                               action:nil],
      [[UIBarButtonItem alloc]
          initWithTitle:@"Apply"
                  style:UIBarButtonItemStyleDone
                 target:self
                 action:@selector(numberTextFieldDidEndEditing:)]
    ];
    [numberToolbar sizeToFit];

    textField.inputAccessoryView = numberToolbar;
    [cell addSubview:textField];
  }
  return cell;
}

- (void)numberTextFieldDidEndEditing:(id)sender {
  [self.view endEditing:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
  NSNumber *bitrateNumber = nil;

  if (textField.text.length != 0) {
    bitrateNumber = [NSNumber numberWithInteger:textField.text.intValue];
  }

  [_settingsModel storeMaxBitrateSetting:bitrateNumber];
}

#pragma mark - Table view delegate(Audio settings)

- (UITableViewCell *)
    audioSettingsTableViewCellForTableView:(UITableView *)tableView
                               atIndexPath:(NSIndexPath *)indexPath {
  NSString *dequeueIdentifier = @"ARDSettingsAudioSettingsCellIdentifier";
  UITableViewCell *cell =
      [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier];
  if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:dequeueIdentifier];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
    switchView.tag = indexPath.row;
    [switchView addTarget:self
                   action:@selector(audioSettingSwitchChanged:)
         forControlEvents:UIControlEventValueChanged];
    cell.accessoryView = switchView;
  }

  cell.textLabel.text = [self labelForAudioSettingAtIndexPathRow:indexPath.row];
  UISwitch *switchView = (UISwitch *)cell.accessoryView;
  switchView.on = [self valueForAudioSettingAtIndexPathRow:indexPath.row];

  return cell;
}

- (NSString *)labelForAudioSettingAtIndexPathRow:(NSInteger)setting {
  switch (setting) {
    case ARDAudioSettingsAudioOnly:
      return @"Audio only";
    case ARDAudioSettingsCreateAecDump:
      return @"Create AecDump";
    case ARDAudioSettingsUseManualAudioConfig:
      return @"Use manual audio config";
    default:
      return @"";
  }
}

- (BOOL)valueForAudioSettingAtIndexPathRow:(NSInteger)setting {
  switch (setting) {
    case ARDAudioSettingsAudioOnly:
      return [_settingsModel currentAudioOnlySettingFromStore];
    case ARDAudioSettingsCreateAecDump:
      return [_settingsModel currentCreateAecDumpSettingFromStore];
    case ARDAudioSettingsUseManualAudioConfig:
      return [_settingsModel currentUseManualAudioConfigSettingFromStore];
    default:
      return NO;
  }
}

- (void)audioSettingSwitchChanged:(UISwitch *)sender {
  switch (sender.tag) {
    case ARDAudioSettingsAudioOnly: {
      [_settingsModel storeAudioOnlySetting:sender.isOn];
      break;
    }
    case ARDAudioSettingsCreateAecDump: {
      [_settingsModel storeCreateAecDumpSetting:sender.isOn];
      break;
    }
    case ARDAudioSettingsUseManualAudioConfig: {
      [_settingsModel storeUseManualAudioConfigSetting:sender.isOn];
      break;
    }
    default:
      break;
  }
}

@end
NS_ASSUME_NONNULL_END
