///|
pub struct HarCacheEntry {
  expires_value : String?
  last_access_value : String
  etag_value : String
  hit_count_value : Double
  comment_value : String?
} derive(Eq, Debug)

///|
pub fn HarCacheEntry::new(
  last_access : String,
  etag : String,
  hit_count : Double,
  expires? : String,
  comment? : String,
) -> Result[HarCacheEntry, HarError] {
  if hit_count.trunc() != hit_count {
    return Err(
      HarError::new(
        InvalidField,
        "$.cache.hitCount",
        "cache hit count must be an integer",
      ),
    )
  }
  if hit_count < 0.0 {
    return Err(
      HarError::new(
        InvalidField,
        "$.cache.hitCount",
        "cache hit count must be non-negative",
      ),
    )
  }
  Ok({
    expires_value: expires,
    last_access_value: last_access,
    etag_value: etag,
    hit_count_value: hit_count,
    comment_value: comment,
  })
}

///|
pub fn HarCacheEntry::expires(self : HarCacheEntry) -> String? {
  self.expires_value
}

///|
pub fn HarCacheEntry::last_access(self : HarCacheEntry) -> String {
  self.last_access_value
}

///|
pub fn HarCacheEntry::etag(self : HarCacheEntry) -> String {
  self.etag_value
}

///|
pub fn HarCacheEntry::hit_count(self : HarCacheEntry) -> Double {
  self.hit_count_value
}

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

///|
pub struct HarCache {
  before_request_value : HarCacheEntry?
  after_request_value : HarCacheEntry?
  comment_value : String?
} derive(Eq, Debug)

///|
pub fn HarCache::new(
  before_request? : HarCacheEntry,
  after_request? : HarCacheEntry,
  comment? : String,
) -> HarCache {
  {
    before_request_value: before_request,
    after_request_value: after_request,
    comment_value: comment,
  }
}

///|
pub fn HarCache::before_request(self : HarCache) -> HarCacheEntry? {
  self.before_request_value
}

///|
pub fn HarCache::after_request(self : HarCache) -> HarCacheEntry? {
  self.after_request_value
}

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

///|
pub fn HarCache::was_cached(self : HarCache) -> Bool {
  self.before_request_value is Some(_)
}

///|
pub fn HarCache::was_updated(self : HarCache) -> Bool {
  self.after_request_value is Some(_)
}

///|
fn parse_cache_entry_cursor(
  cursor : JsonCursor,
) -> Result[HarCacheEntry, HarError] {
  let expires = match cursor.optional_string("expires") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let last_access = match cursor.required_string("lastAccess") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let etag = match cursor.required_string("eTag") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let hit_count = match cursor.required_number("hitCount") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let comment = match cursor.optional_string("comment") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  if hit_count.trunc() != hit_count {
    return Err(
      HarError::new(
        InvalidField,
        append_json_field(cursor.path(), "hitCount"),
        "cache hit count must be an integer",
      ),
    )
  }
  if hit_count < 0.0 {
    return Err(
      HarError::new(
        InvalidField,
        append_json_field(cursor.path(), "hitCount"),
        "cache hit count must be non-negative",
      ),
    )
  }
  Ok({
    expires_value: expires,
    last_access_value: last_access,
    etag_value: etag,
    hit_count_value: hit_count,
    comment_value: comment,
  })
}

///|
fn parse_cache_cursor(cursor : JsonCursor) -> Result[HarCache, HarError] {
  let before_cursor = match cursor.optional_object("beforeRequest") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let before_request = match before_cursor {
    Some(value) =>
      match parse_cache_entry_cursor(value) {
        Ok(entry) => Some(entry)
        Err(error) => return Err(error)
      }
    None => None
  }
  let after_cursor = match cursor.optional_object("afterRequest") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let after_request = match after_cursor {
    Some(value) =>
      match parse_cache_entry_cursor(value) {
        Ok(entry) => Some(entry)
        Err(error) => return Err(error)
      }
    None => None
  }
  let comment = match cursor.optional_string("comment") {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  Ok({
    before_request_value: before_request,
    after_request_value: after_request,
    comment_value: comment,
  })
}

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