///|
pub struct HarBatchInput {
  label_value : String
  text_value : String
} derive(Eq, Debug)

///|
pub fn HarBatchInput::new(
  label : String,
  text : String,
) -> Result[HarBatchInput, HarError] {
  if label.trim().is_empty() {
    return Err(
      HarError::new(
        InvalidField,
        "$.batch.label",
        "batch input label cannot be empty",
      ),
    )
  }
  Ok({ label_value: label, text_value: text })
}

///|
pub fn HarBatchInput::label(self : HarBatchInput) -> String {
  self.label_value
}

///|
pub fn HarBatchInput::text(self : HarBatchInput) -> String {
  self.text_value
}

///|
pub struct HarBatchItem {
  label_value : String
  document_value : HarDocument?
  error_value : HarError?
} derive(Eq, Debug)

///|
pub fn HarBatchItem::label(self : HarBatchItem) -> String {
  self.label_value
}

///|
pub fn HarBatchItem::document(self : HarBatchItem) -> HarDocument? {
  self.document_value
}

///|
pub fn HarBatchItem::error(self : HarBatchItem) -> HarError? {
  self.error_value
}

///|
pub fn HarBatchItem::accepted(self : HarBatchItem) -> Bool {
  self.document_value is Some(_)
}

///|
pub struct HarBatchResult {
  items_value : Array[HarBatchItem]
  accepted_value : Int
  rejected_value : Int
  total_entries_value : Int
  total_input_bytes_value : Int
} derive(Eq, Debug)

///|
pub fn HarBatchResult::items(self : HarBatchResult) -> Array[HarBatchItem] {
  self.items_value.copy()
}

///|
pub fn HarBatchResult::accepted(self : HarBatchResult) -> Int {
  self.accepted_value
}

///|
pub fn HarBatchResult::rejected(self : HarBatchResult) -> Int {
  self.rejected_value
}

///|
pub fn HarBatchResult::total_entries(self : HarBatchResult) -> Int {
  self.total_entries_value
}

///|
pub fn HarBatchResult::total_input_bytes(self : HarBatchResult) -> Int {
  self.total_input_bytes_value
}

///|
pub fn HarBatchResult::find(
  self : HarBatchResult,
  label : String,
) -> HarBatchItem? {
  for item in self.items_value {
    if item.label_value == label {
      return Some(item)
    }
  }
  None
}

///|
fn duplicate_batch_label(inputs : Array[HarBatchInput], index : Int) -> Bool {
  let label = inputs[index].label_value
  for previous = 0; previous < index; previous = previous + 1 {
    if inputs[previous].label_value == label {
      return true
    }
  }
  false
}

///|
pub fn parse_har_batch(
  inputs : Array[HarBatchInput],
  max_items : Int,
  max_total_input_bytes : Int,
  limits? : HarLimits = HarLimits::standard(),
) -> Result[HarBatchResult, HarError] {
  if max_items < 0 || max_total_input_bytes < 0 {
    return Err(
      HarError::new(InvalidField, "$.batch", "batch limits cannot be negative"),
    )
  }
  if inputs.length() > max_items {
    return Err(limit_error("$.batch.items", inputs.length(), max_items))
  }
  let mut total_input_bytes = 0
  for index, input in inputs {
    if duplicate_batch_label(inputs, index) {
      return Err(
        HarError::new(
          DuplicateIdentifier,
          append_json_field(append_json_index("$.batch.items", index), "label"),
          "batch labels must be unique",
        ),
      )
    }
    total_input_bytes += input.text_value.length()
    if total_input_bytes > max_total_input_bytes {
      return Err(
        limit_error(
          "$.batch.total_input_bytes", total_input_bytes, max_total_input_bytes,
        ),
      )
    }
  }
  let items : Array[HarBatchItem] = []
  let mut accepted = 0
  let mut rejected = 0
  let mut total_entries = 0
  for input in inputs {
    match parse_har_with_limits(input.text_value, limits) {
      Ok(document) => {
        accepted += 1
        total_entries += document.entry_count()
        items.push({
          label_value: input.label_value,
          document_value: Some(document),
          error_value: None,
        })
      }
      Err(error) => {
        rejected += 1
        items.push({
          label_value: input.label_value,
          document_value: None,
          error_value: Some(error),
        })
      }
    }
  }
  Ok({
    items_value: items,
    accepted_value: accepted,
    rejected_value: rejected,
    total_entries_value: total_entries,
    total_input_bytes_value: total_input_bytes,
  })
}