#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
{{#apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}}
{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}}
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;

extern crate swagger;

use futures::Stream;
use std::io::Error;

#[allow(unused_imports)]
use std::collections::HashMap;

pub use futures::Future;

#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;

pub use swagger::{ApiError, ContextWrapper};

pub const BASE_PATH: &'static str = "{{basePathWithoutHost}}";
pub const API_VERSION: &'static str = "{{appVersion}}";

{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{^isResponseFile}}
#[derive(Debug, PartialEq)]
{{/isResponseFile}}
pub enum {{operationId}}Response {
{{#responses}}
{{#message}}    /// {{message}}{{/message}}
    {{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}} {{#dataType}}{{^headers}}( {{{dataType}}} ) {{/headers}}{{#headers}}{{#-first}}{ body: {{{dataType}}}{{/-first}}{{/headers}}{{/dataType}}{{#headers}}{{#-first}}{{^dataType}} { {{/dataType}}{{#dataType}}, {{/dataType}}{{/-first}}{{^-first}}, {{/-first}}{{name}}: {{{datatype}}}{{#-last}} } {{/-last}}{{/headers}},
{{/responses}}
}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

/// API
pub trait Api<C> {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}}    /// {{{summary}}}{{/summary}}
    fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box<Future<Item={{operationId}}Response, Error=ApiError>>;
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}

/// API without a `Context`
pub trait ApiNoContext {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}}    /// {{{summary}}}{{/summary}}
    fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box<Future<Item={{operationId}}Response, Error=ApiError>>;
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}

/// Trait to extend an API to make it easy to bind it to a context.
pub trait ContextWrapperExt<'a, C> where Self: Sized {
    /// Binds this API to a context.
    fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>;
}

impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
    fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> {
         ContextWrapper::<T, C>::new(self, context)
    }
}

impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}}    /// {{{summary}}}{{/summary}}
    fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box<Future<Item={{operationId}}Response, Error=ApiError>> {
        self.api().{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{paramName}}, {{/allParams}}&self.context())
    }
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}

#[cfg(feature = "client")]
pub mod client;

// Re-export Client as a top-level name
#[cfg(feature = "client")]
pub use self::client::Client;

#[cfg(feature = "server")]
pub mod server;

// Re-export router() as a top-level name
#[cfg(feature = "server")]
pub use self::server::Service;

pub mod models;
