/*
 *  Copyright 2019 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 "RTCStatisticsReport+Private.h"

#include "helpers/NSString+StdString.h"
#include "rtc_base/checks.h"

namespace webrtc {

/** Converts a single value to a suitable NSNumber, NSString or NSArray containing NSNumbers
    or NSStrings, or NSDictionary of NSString keys to NSNumber values.*/
NSObject *ValueFromStatsMember(const RTCStatsMemberInterface *member) {
  if (member->is_defined()) {
    switch (member->type()) {
      case RTCStatsMemberInterface::kBool:
        return [NSNumber numberWithBool:*member->cast_to<RTCStatsMember<bool>>()];
      case RTCStatsMemberInterface::kInt32:
        return [NSNumber numberWithInt:*member->cast_to<RTCStatsMember<int32_t>>()];
      case RTCStatsMemberInterface::kUint32:
        return [NSNumber numberWithUnsignedInt:*member->cast_to<RTCStatsMember<uint32_t>>()];
      case RTCStatsMemberInterface::kInt64:
        return [NSNumber numberWithLong:*member->cast_to<RTCStatsMember<int64_t>>()];
      case RTCStatsMemberInterface::kUint64:
        return [NSNumber numberWithUnsignedLong:*member->cast_to<RTCStatsMember<uint64_t>>()];
      case RTCStatsMemberInterface::kDouble:
        return [NSNumber numberWithDouble:*member->cast_to<RTCStatsMember<double>>()];
      case RTCStatsMemberInterface::kString:
        return [NSString stringForStdString:*member->cast_to<RTCStatsMember<std::string>>()];
      case RTCStatsMemberInterface::kSequenceBool: {
        std::vector<bool> sequence = *member->cast_to<RTCStatsMember<std::vector<bool>>>();
        NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (auto item : sequence) {
          [array addObject:[NSNumber numberWithBool:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kSequenceInt32: {
        std::vector<int32_t> sequence = *member->cast_to<RTCStatsMember<std::vector<int32_t>>>();
        NSMutableArray<NSNumber *> *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (const auto &item : sequence) {
          [array addObject:[NSNumber numberWithInt:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kSequenceUint32: {
        std::vector<uint32_t> sequence = *member->cast_to<RTCStatsMember<std::vector<uint32_t>>>();
        NSMutableArray<NSNumber *> *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (const auto &item : sequence) {
          [array addObject:[NSNumber numberWithUnsignedInt:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kSequenceInt64: {
        std::vector<int64_t> sequence = *member->cast_to<RTCStatsMember<std::vector<int64_t>>>();
        NSMutableArray<NSNumber *> *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (const auto &item : sequence) {
          [array addObject:[NSNumber numberWithLong:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kSequenceUint64: {
        std::vector<uint64_t> sequence = *member->cast_to<RTCStatsMember<std::vector<uint64_t>>>();
        NSMutableArray<NSNumber *> *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (const auto &item : sequence) {
          [array addObject:[NSNumber numberWithUnsignedLong:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kSequenceDouble: {
        std::vector<double> sequence = *member->cast_to<RTCStatsMember<std::vector<double>>>();
        NSMutableArray<NSNumber *> *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (const auto &item : sequence) {
          [array addObject:[NSNumber numberWithDouble:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kSequenceString: {
        std::vector<std::string> sequence =
            *member->cast_to<RTCStatsMember<std::vector<std::string>>>();
        NSMutableArray<NSString *> *array = [NSMutableArray arrayWithCapacity:sequence.size()];
        for (const auto &item : sequence) {
          [array addObject:[NSString stringForStdString:item]];
        }
        return [array copy];
      }
      case RTCStatsMemberInterface::kMapStringUint64: {
        std::map<std::string, uint64_t> map =
            *member->cast_to<RTCStatsMember<std::map<std::string, uint64_t>>>();
        NSMutableDictionary<NSString *, NSNumber *> *dictionary =
            [NSMutableDictionary dictionaryWithCapacity:map.size()];
        for (const auto &item : map) {
          dictionary[[NSString stringForStdString:item.first]] = @(item.second);
        }
        return [dictionary copy];
      }
      case RTCStatsMemberInterface::kMapStringDouble: {
        std::map<std::string, double> map =
            *member->cast_to<RTCStatsMember<std::map<std::string, double>>>();
        NSMutableDictionary<NSString *, NSNumber *> *dictionary =
            [NSMutableDictionary dictionaryWithCapacity:map.size()];
        for (const auto &item : map) {
          dictionary[[NSString stringForStdString:item.first]] = @(item.second);
        }
        return [dictionary copy];
      }
      default:
        RTC_DCHECK_NOTREACHED();
    }
  }

  return nil;
}
}  // namespace webrtc

@implementation RTC_OBJC_TYPE (RTCStatistics)

@synthesize id = _id;
@synthesize timestamp_us = _timestamp_us;
@synthesize type = _type;
@synthesize values = _values;

- (instancetype)initWithStatistics:(const webrtc::RTCStats &)statistics {
  if (self = [super init]) {
    _id = [NSString stringForStdString:statistics.id()];
    _timestamp_us = statistics.timestamp_us();
    _type = [NSString stringWithCString:statistics.type() encoding:NSUTF8StringEncoding];

    NSMutableDictionary<NSString *, NSObject *> *values = [NSMutableDictionary dictionary];
    for (const webrtc::RTCStatsMemberInterface *member : statistics.Members()) {
      NSObject *value = ValueFromStatsMember(member);
      if (value) {
        NSString *name = [NSString stringWithCString:member->name() encoding:NSUTF8StringEncoding];
        RTC_DCHECK(name.length > 0);
        RTC_DCHECK(!values[name]);
        values[name] = value;
      }
    }
    _values = [values copy];
  }

  return self;
}

- (NSString *)description {
  return [NSString stringWithFormat:@"id = %@, type = %@, timestamp = %.0f, values = %@",
                                    self.id,
                                    self.type,
                                    self.timestamp_us,
                                    self.values];
}

@end

@implementation RTC_OBJC_TYPE (RTCStatisticsReport)

@synthesize timestamp_us = _timestamp_us;
@synthesize statistics = _statistics;

- (NSString *)description {
  return [NSString
      stringWithFormat:@"timestamp = %.0f, statistics = %@", self.timestamp_us, self.statistics];
}

@end

@implementation RTC_OBJC_TYPE (RTCStatisticsReport) (Private)

- (instancetype)initWithReport : (const webrtc::RTCStatsReport &)report {
  if (self = [super init]) {
    _timestamp_us = report.timestamp_us();

    NSMutableDictionary *statisticsById =
        [NSMutableDictionary dictionaryWithCapacity:report.size()];
    for (const auto &stat : report) {
      RTC_OBJC_TYPE(RTCStatistics) *statistics =
          [[RTC_OBJC_TYPE(RTCStatistics) alloc] initWithStatistics:stat];
      statisticsById[statistics.id] = statistics;
    }
    _statistics = [statisticsById copy];
  }

  return self;
}

@end
