// Code generated by protoc-gen-ts-client. DO NOT EDIT.
// source: worldmonitor/military/v1/service.proto

export interface ListMilitaryFlightsRequest {
  pageSize: number;
  cursor: string;
  neLat: number;
  neLon: number;
  swLat: number;
  swLon: number;
  operator: MilitaryOperator;
  aircraftType: MilitaryAircraftType;
}

export interface ListMilitaryFlightsResponse {
  flights: MilitaryFlight[];
  clusters: MilitaryFlightCluster[];
  pagination?: PaginationResponse;
}

export interface MilitaryFlight {
  id: string;
  callsign: string;
  hexCode: string;
  registration: string;
  aircraftType: MilitaryAircraftType;
  aircraftModel: string;
  operator: MilitaryOperator;
  operatorCountry: string;
  location?: GeoCoordinates;
  altitude: number;
  heading: number;
  speed: number;
  verticalRate: number;
  onGround: boolean;
  squawk: string;
  origin: string;
  destination: string;
  lastSeenAt: number;
  firstSeenAt: number;
  confidence: MilitaryConfidence;
  isInteresting: boolean;
  note: string;
  enrichment?: FlightEnrichment;
}

export interface GeoCoordinates {
  latitude: number;
  longitude: number;
}

export interface FlightEnrichment {
  manufacturer: string;
  owner: string;
  operatorName: string;
  typeCode: string;
  builtYear: string;
  confirmedMilitary: boolean;
  militaryBranch: string;
}

export interface MilitaryFlightCluster {
  id: string;
  name: string;
  location?: GeoCoordinates;
  flightCount: number;
  flights: MilitaryFlight[];
  dominantOperator: MilitaryOperator;
  activityType: MilitaryActivityType;
}

export interface PaginationResponse {
  nextCursor: string;
  totalCount: number;
}

export interface GetTheaterPostureRequest {
  theater: string;
}

export interface GetTheaterPostureResponse {
  theaters: TheaterPosture[];
}

export interface TheaterPosture {
  theater: string;
  postureLevel: string;
  activeFlights: number;
  trackedVessels: number;
  activeOperations: string[];
  assessedAt: number;
}

export interface GetAircraftDetailsRequest {
  icao24: string;
}

export interface GetAircraftDetailsResponse {
  details?: AircraftDetails;
  configured: boolean;
}

export interface AircraftDetails {
  icao24: string;
  registration: string;
  manufacturerIcao: string;
  manufacturerName: string;
  model: string;
  typecode: string;
  serialNumber: string;
  icaoAircraftType: string;
  operator: string;
  operatorCallsign: string;
  operatorIcao: string;
  owner: string;
  built: string;
  engines: string;
  categoryDescription: string;
}

export interface GetAircraftDetailsBatchRequest {
  icao24s: string[];
}

export interface GetAircraftDetailsBatchResponse {
  results: Record<string, AircraftDetails>;
  fetched: number;
  requested: number;
  configured: boolean;
}

export interface GetWingbitsStatusRequest {
}

export interface GetWingbitsStatusResponse {
  configured: boolean;
}

export interface GetUSNIFleetReportRequest {
  forceRefresh: boolean;
}

export interface GetUSNIFleetReportResponse {
  report?: USNIFleetReport;
  cached: boolean;
  stale: boolean;
  error: string;
}

export interface USNIFleetReport {
  articleUrl: string;
  articleDate: string;
  articleTitle: string;
  battleForceSummary?: BattleForceSummary;
  vessels: USNIVessel[];
  strikeGroups: USNIStrikeGroup[];
  regions: string[];
  parsingWarnings: string[];
  timestamp: number;
}

export interface BattleForceSummary {
  totalShips: number;
  deployed: number;
  underway: number;
}

export interface USNIVessel {
  name: string;
  hullNumber: string;
  vesselType: string;
  region: string;
  regionLat: number;
  regionLon: number;
  deploymentStatus: string;
  homePort: string;
  strikeGroup: string;
  activityDescription: string;
  articleUrl: string;
  articleDate: string;
}

export interface USNIStrikeGroup {
  name: string;
  carrier: string;
  airWing: string;
  destroyerSquadron: string;
  escorts: string[];
}

export interface ListMilitaryBasesRequest {
  neLat: number;
  neLon: number;
  swLat: number;
  swLon: number;
  zoom: number;
  type: string;
  kind: string;
  country: string;
}

export interface ListMilitaryBasesResponse {
  bases: MilitaryBaseEntry[];
  clusters: MilitaryBaseCluster[];
  totalInView: number;
  truncated: boolean;
}

export interface MilitaryBaseEntry {
  id: string;
  name: string;
  latitude: number;
  longitude: number;
  kind: string;
  countryIso2: string;
  type: string;
  tier: number;
  catAirforce: boolean;
  catNaval: boolean;
  catNuclear: boolean;
  catSpace: boolean;
  catTraining: boolean;
  branch: string;
  status: string;
}

export interface MilitaryBaseCluster {
  latitude: number;
  longitude: number;
  count: number;
  dominantType: string;
  expansionZoom: number;
}

export interface GetWingbitsLiveFlightRequest {
  icao24: string;
}

export interface GetWingbitsLiveFlightResponse {
  flight?: WingbitsLiveFlight;
}

export interface WingbitsLiveFlight {
  icao24: string;
  callsign: string;
  lat: number;
  lon: number;
  altitude: number;
  speed: number;
  heading: number;
  verticalRate: number;
  registration: string;
  model: string;
  operator: string;
  onGround: boolean;
  lastSeen: string;
  depIata: string;
  arrIata: string;
  depTimeUtc: string;
  arrTimeUtc: string;
  depEstimatedUtc: string;
  arrEstimatedUtc: string;
  depDelayedMin: number;
  arrDelayedMin: number;
  flightStatus: string;
  flightDurationMin: number;
  arrTerminal: string;
  photoUrl: string;
  photoLink: string;
  photoCredit: string;
  callsignIata: string;
  airlineName: string;
}

export interface ListDefensePatentsRequest {
  cpcCode: string;
  assignee: string;
  limit: number;
}

export interface ListDefensePatentsResponse {
  patents: DefensePatentFiling[];
  total: number;
  fetchedAt: string;
}

export interface DefensePatentFiling {
  patentId: string;
  title: string;
  date: string;
  assignee: string;
  cpcCode: string;
  cpcDesc: string;
  abstract: string;
  url: string;
}

export type MilitaryActivityType = "MILITARY_ACTIVITY_TYPE_UNSPECIFIED" | "MILITARY_ACTIVITY_TYPE_EXERCISE" | "MILITARY_ACTIVITY_TYPE_PATROL" | "MILITARY_ACTIVITY_TYPE_TRANSPORT" | "MILITARY_ACTIVITY_TYPE_DEPLOYMENT" | "MILITARY_ACTIVITY_TYPE_TRANSIT" | "MILITARY_ACTIVITY_TYPE_UNKNOWN";

export type MilitaryAircraftType = "MILITARY_AIRCRAFT_TYPE_UNSPECIFIED" | "MILITARY_AIRCRAFT_TYPE_FIGHTER" | "MILITARY_AIRCRAFT_TYPE_BOMBER" | "MILITARY_AIRCRAFT_TYPE_TRANSPORT" | "MILITARY_AIRCRAFT_TYPE_TANKER" | "MILITARY_AIRCRAFT_TYPE_AWACS" | "MILITARY_AIRCRAFT_TYPE_RECONNAISSANCE" | "MILITARY_AIRCRAFT_TYPE_HELICOPTER" | "MILITARY_AIRCRAFT_TYPE_DRONE" | "MILITARY_AIRCRAFT_TYPE_PATROL" | "MILITARY_AIRCRAFT_TYPE_SPECIAL_OPS" | "MILITARY_AIRCRAFT_TYPE_VIP" | "MILITARY_AIRCRAFT_TYPE_UNKNOWN";

export type MilitaryConfidence = "MILITARY_CONFIDENCE_UNSPECIFIED" | "MILITARY_CONFIDENCE_LOW" | "MILITARY_CONFIDENCE_MEDIUM" | "MILITARY_CONFIDENCE_HIGH";

export type MilitaryOperator = "MILITARY_OPERATOR_UNSPECIFIED" | "MILITARY_OPERATOR_USAF" | "MILITARY_OPERATOR_USN" | "MILITARY_OPERATOR_USMC" | "MILITARY_OPERATOR_USA" | "MILITARY_OPERATOR_RAF" | "MILITARY_OPERATOR_RN" | "MILITARY_OPERATOR_FAF" | "MILITARY_OPERATOR_GAF" | "MILITARY_OPERATOR_PLAAF" | "MILITARY_OPERATOR_PLAN" | "MILITARY_OPERATOR_VKS" | "MILITARY_OPERATOR_IAF" | "MILITARY_OPERATOR_NATO" | "MILITARY_OPERATOR_OTHER";

export interface FieldViolation {
  field: string;
  description: string;
}

export class ValidationError extends Error {
  violations: FieldViolation[];

  constructor(violations: FieldViolation[]) {
    super("Validation failed");
    this.name = "ValidationError";
    this.violations = violations;
  }
}

export class ApiError extends Error {
  statusCode: number;
  body: string;

  constructor(statusCode: number, message: string, body: string) {
    super(message);
    this.name = "ApiError";
    this.statusCode = statusCode;
    this.body = body;
  }
}

export interface MilitaryServiceClientOptions {
  fetch?: typeof fetch;
  defaultHeaders?: Record<string, string>;
}

export interface MilitaryServiceCallOptions {
  headers?: Record<string, string>;
  signal?: AbortSignal;
}

export class MilitaryServiceClient {
  private baseURL: string;
  private fetchFn: typeof fetch;
  private defaultHeaders: Record<string, string>;

  constructor(baseURL: string, options?: MilitaryServiceClientOptions) {
    this.baseURL = baseURL.replace(/\/+$/, "");
    this.fetchFn = options?.fetch ?? globalThis.fetch;
    this.defaultHeaders = { ...options?.defaultHeaders };
  }

  async listMilitaryFlights(req: ListMilitaryFlightsRequest, options?: MilitaryServiceCallOptions): Promise<ListMilitaryFlightsResponse> {
    let path = "/api/military/v1/list-military-flights";
    const params = new URLSearchParams();
    if (req.pageSize != null && req.pageSize !== 0) params.set("page_size", String(req.pageSize));
    if (req.cursor != null && req.cursor !== "") params.set("cursor", String(req.cursor));
    if (req.neLat != null && req.neLat !== 0) params.set("ne_lat", String(req.neLat));
    if (req.neLon != null && req.neLon !== 0) params.set("ne_lon", String(req.neLon));
    if (req.swLat != null && req.swLat !== 0) params.set("sw_lat", String(req.swLat));
    if (req.swLon != null && req.swLon !== 0) params.set("sw_lon", String(req.swLon));
    if (req.operator != null && req.operator !== "MILITARY_OPERATOR_UNSPECIFIED") params.set("operator", String(req.operator));
    if (req.aircraftType != null && req.aircraftType !== "MILITARY_AIRCRAFT_TYPE_UNSPECIFIED") params.set("aircraft_type", String(req.aircraftType));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as ListMilitaryFlightsResponse;
  }

  async getTheaterPosture(req: GetTheaterPostureRequest, options?: MilitaryServiceCallOptions): Promise<GetTheaterPostureResponse> {
    let path = "/api/military/v1/get-theater-posture";
    const params = new URLSearchParams();
    if (req.theater != null && req.theater !== "") params.set("theater", String(req.theater));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetTheaterPostureResponse;
  }

  async getAircraftDetails(req: GetAircraftDetailsRequest, options?: MilitaryServiceCallOptions): Promise<GetAircraftDetailsResponse> {
    let path = "/api/military/v1/get-aircraft-details";
    const params = new URLSearchParams();
    if (req.icao24 != null && req.icao24 !== "") params.set("icao24", String(req.icao24));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetAircraftDetailsResponse;
  }

  async getAircraftDetailsBatch(req: GetAircraftDetailsBatchRequest, options?: MilitaryServiceCallOptions): Promise<GetAircraftDetailsBatchResponse> {
    let path = "/api/military/v1/get-aircraft-details-batch";
    const url = this.baseURL + path;

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "POST",
      headers,
      body: JSON.stringify(req),
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetAircraftDetailsBatchResponse;
  }

  async getWingbitsStatus(_req: GetWingbitsStatusRequest, options?: MilitaryServiceCallOptions): Promise<GetWingbitsStatusResponse> {
    let path = "/api/military/v1/get-wingbits-status";
    const url = this.baseURL + path;

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetWingbitsStatusResponse;
  }

  async getUSNIFleetReport(req: GetUSNIFleetReportRequest, options?: MilitaryServiceCallOptions): Promise<GetUSNIFleetReportResponse> {
    let path = "/api/military/v1/get-usni-fleet-report";
    const params = new URLSearchParams();
    if (req.forceRefresh) params.set("force_refresh", String(req.forceRefresh));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetUSNIFleetReportResponse;
  }

  async listMilitaryBases(req: ListMilitaryBasesRequest, options?: MilitaryServiceCallOptions): Promise<ListMilitaryBasesResponse> {
    let path = "/api/military/v1/list-military-bases";
    const params = new URLSearchParams();
    if (req.neLat != null && req.neLat !== 0) params.set("ne_lat", String(req.neLat));
    if (req.neLon != null && req.neLon !== 0) params.set("ne_lon", String(req.neLon));
    if (req.swLat != null && req.swLat !== 0) params.set("sw_lat", String(req.swLat));
    if (req.swLon != null && req.swLon !== 0) params.set("sw_lon", String(req.swLon));
    if (req.zoom != null && req.zoom !== 0) params.set("zoom", String(req.zoom));
    if (req.type != null && req.type !== "") params.set("type", String(req.type));
    if (req.kind != null && req.kind !== "") params.set("kind", String(req.kind));
    if (req.country != null && req.country !== "") params.set("country", String(req.country));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as ListMilitaryBasesResponse;
  }

  async getWingbitsLiveFlight(req: GetWingbitsLiveFlightRequest, options?: MilitaryServiceCallOptions): Promise<GetWingbitsLiveFlightResponse> {
    let path = "/api/military/v1/get-wingbits-live-flight";
    const params = new URLSearchParams();
    if (req.icao24 != null && req.icao24 !== "") params.set("icao24", String(req.icao24));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetWingbitsLiveFlightResponse;
  }

  async listDefensePatents(req: ListDefensePatentsRequest, options?: MilitaryServiceCallOptions): Promise<ListDefensePatentsResponse> {
    let path = "/api/military/v1/list-defense-patents";
    const params = new URLSearchParams();
    if (req.cpcCode != null && req.cpcCode !== "") params.set("cpc_code", String(req.cpcCode));
    if (req.assignee != null && req.assignee !== "") params.set("assignee", String(req.assignee));
    if (req.limit != null && req.limit !== 0) params.set("limit", String(req.limit));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as ListDefensePatentsResponse;
  }

  private async handleError(resp: Response): Promise<never> {
    const body = await resp.text();
    if (resp.status === 400) {
      try {
        const parsed = JSON.parse(body);
        if (parsed.violations) {
          throw new ValidationError(parsed.violations);
        }
      } catch (e) {
        if (e instanceof ValidationError) throw e;
      }
    }
    throw new ApiError(resp.status, `Request failed with status ${resp.status}`, body);
  }
}

