///|
pub struct HarEntry {
  page_ref_value : String?
  started_datetime_value : String
  time_value : Double
  request_value : HarRequest
  response_value : HarResponse
  cache_value : HarCache
  timings_value : HarTimings
  server_ip_value : String?
  connection_value : String?
  comment_value : String?
} derive(Eq, Debug)

///|
pub fn HarEntry::page_ref(self : HarEntry) -> String? {
  self.page_ref_value
}

///|
pub fn HarEntry::started_datetime(self : HarEntry) -> String {
  self.started_datetime_value
}

///|
pub fn HarEntry::time(self : HarEntry) -> Double {
  self.time_value
}

///|
pub fn HarEntry::request(self : HarEntry) -> HarRequest {
  self.request_value
}

///|
pub fn HarEntry::response(self : HarEntry) -> HarResponse {
  self.response_value
}

///|
pub fn HarEntry::cache(self : HarEntry) -> HarCache {
  self.cache_value
}

///|
pub fn HarEntry::timings(self : HarEntry) -> HarTimings {
  self.timings_value
}

///|
pub fn HarEntry::server_ip_address(self : HarEntry) -> String? {
  self.server_ip_value
}

///|
pub fn HarEntry::connection(self : HarEntry) -> String? {
  self.connection_value
}

///|
pub fn HarEntry::comment(self : HarEntry) -> String? {
  self.comment_value
}

///|
pub fn HarEntry::timing_delta(self : HarEntry) -> Double {
  self.time_value - self.timings_value.known_total()
}

///|
pub fn HarEntry::transferred_body_size(self : HarEntry) -> Double? {
  self.response_value.known_body_size()
}

///|
pub fn HarEntry::decoded_body_size(self : HarEntry) -> Double? {
  self.response_value.content().known_size()
}

///|
pub fn HarEntry::is_page_entry(self : HarEntry, page_id : String) -> Bool {
  match self.page_ref_value {
    Some(value) => value == page_id
    None => false
  }
}

///|
fn parse_entry_cursor(cursor : JsonCursor) -> Result[HarEntry, HarError] {
  let page_ref = match cursor.optional_string("pageref") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let started = match cursor.required_string("startedDateTime") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  match
    validate_datetime(
      started,
      append_json_field(cursor.path(), "startedDateTime"),
    ) {
    Ok(_) => ()
    Err(error) => return Err(error)
  }
  let time = match cursor.required_number("time") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  if time < 0.0 {
    return Err(
      HarError::new(
        InvalidTiming,
        append_json_field(cursor.path(), "time"),
        "entry time must be non-negative",
      ),
    )
  }
  let request_cursor = match cursor.required_object("request") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let request = match parse_request_cursor(request_cursor) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let response_cursor = match cursor.required_object("response") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let response = match parse_response_cursor(response_cursor) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let cache_cursor = match cursor.required_object("cache") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let cache = match parse_cache_cursor(cache_cursor) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let timings_cursor = match cursor.required_object("timings") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let timings = match parse_timings_cursor(timings_cursor) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let server_ip = match cursor.optional_string("serverIPAddress") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let connection = match cursor.optional_string("connection") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let comment = match cursor.optional_string("comment") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  Ok({
    page_ref_value: page_ref,
    started_datetime_value: started,
    time_value: time,
    request_value: request,
    response_value: response,
    cache_value: cache,
    timings_value: timings,
    server_ip_value: server_ip,
    connection_value: connection,
    comment_value: comment,
  })
}

///|
pub fn parse_entry(input : String) -> Result[HarEntry, HarError] {
  let cursor = match parse_json_cursor(input) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  parse_entry_cursor(cursor)
}