use graphql_parser::query::{ParseError, Value};
use graphql_parser::Pos;
use std::fmt::Debug;
#[derive(Clone, Debug)]
pub struct FieldError(pub String, pub Option<serde_json::Value>);
impl FieldError {
    #[doc(hidden)]
    pub fn into_error(self, pos: Pos) -> Error {
        Error::Query {
            pos,
            path: None,
            err: QueryError::FieldError {
                err: self.0,
                extended_error: self.1,
            },
        }
    }
    #[doc(hidden)]
    pub fn into_error_with_path(self, pos: Pos, path: serde_json::Value) -> Error {
        Error::Query {
            pos,
            path: Some(path),
            err: QueryError::FieldError {
                err: self.0,
                extended_error: self.1,
            },
        }
    }
}
pub type FieldResult<T> = std::result::Result<T, FieldError>;
impl<E> From<E> for FieldError
where
    E: std::fmt::Display + Send + Sync + 'static,
{
    fn from(err: E) -> Self {
        FieldError(format!("{}", err), None)
    }
}
#[allow(missing_docs)]
pub trait ErrorExtensions
where
    Self: Sized,
{
    fn extend(&self) -> FieldError;
    fn extend_with<C>(self, cb: C) -> FieldError
    where
        C: FnOnce(&Self) -> serde_json::Value,
    {
        let name = self.extend().0;
        if let Some(mut base) = self.extend().1 {
            let mut cb_res = cb(&self);
            if let Some(base_map) = base.as_object_mut() {
                if let Some(cb_res_map) = cb_res.as_object_mut() {
                    base_map.append(cb_res_map);
                }
                return FieldError(name, Some(serde_json::json!(base_map)));
            } else {
                return FieldError(name, Some(cb_res));
            }
        }
        FieldError(name, Some(cb(&self)))
    }
}
impl ErrorExtensions for FieldError {
    fn extend(&self) -> FieldError {
        self.clone()
    }
}
impl<E: std::fmt::Display> ErrorExtensions for &E {
    fn extend(&self) -> FieldError {
        FieldError(format!("{}", self), None)
    }
}
#[allow(missing_docs)]
pub trait ResultExt<T, E>
where
    Self: Sized,
{
    fn extend_err<CB>(self, cb: CB) -> FieldResult<T>
    where
        CB: FnOnce(&E) -> serde_json::Value;
    fn extend(self) -> FieldResult<T>;
}
impl<T, E> ResultExt<T, E> for std::result::Result<T, E>
where
    E: ErrorExtensions + Send + Sync + 'static,
{
    fn extend_err<C>(self, cb: C) -> FieldResult<T>
    where
        C: FnOnce(&E) -> serde_json::Value,
    {
        match self {
            Err(err) => Err(err.extend_with(|e| cb(e))),
            Ok(value) => Ok(value),
        }
    }
    fn extend(self) -> FieldResult<T> {
        match self {
            Err(err) => Err(err.extend()),
            Ok(value) => Ok(value),
        }
    }
}
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum QueryError {
    #[error("Not supported.")]
    NotSupported,
    #[error("Expected type \"{expect}\", found {actual}.")]
    ExpectedType {
        
        expect: String,
        
        actual: Value,
    },
    #[error("Expected type \"{expect}\", found {actual}.")]
    ExpectedJsonType {
        
        expect: String,
        
        actual: serde_json::Value,
    },
    #[error("Cannot query field \"{field_name}\" on type \"{object}\".")]
    FieldNotFound {
        
        field_name: String,
        
        object: String,
    },
    #[error("Missing operation")]
    MissingOperation,
    #[error("Unknown operation named \"{name}\"")]
    UnknownOperationNamed {
        
        name: String,
    },
    #[error("Type \"{object}\" must have a selection of subfields.")]
    MustHaveSubFields {
        
        object: String,
    },
    #[error("Schema is not configured for mutations.")]
    NotConfiguredMutations,
    #[error("Schema is not configured for subscriptions.")]
    NotConfiguredSubscriptions,
    #[error("Invalid value for enum \"{ty}\".")]
    InvalidEnumValue {
        
        ty: String,
        
        value: String,
    },
    #[error("Required field \"{field_name}\" for InputObject \"{object}\" does not exist.")]
    RequiredField {
        
        field_name: String,
        
        object: &'static str,
    },
    #[error("Variable \"${var_name}\" is not defined")]
    VarNotDefined {
        
        var_name: String,
    },
    #[error(
        "Directive \"{directive}\" argument \"{arg_name}\" of type \"{arg_type}\" is required, but it was not provided."
    )]
    RequiredDirectiveArgs {
        
        directive: &'static str,
        
        arg_name: &'static str,
        
        arg_type: &'static str,
    },
    #[error("Unknown directive \"{name}\".")]
    UnknownDirective {
        
        name: String,
    },
    #[error("Unknown fragment \"{name}\".")]
    UnknownFragment {
        
        name: String,
    },
    #[error("Object \"{object}\" does not implement interface \"{interface}\"")]
    NotImplementedInterface {
        
        object: String,
        
        interface: String,
    },
    #[error("Unrecognized inline fragment \"{name}\" on type \"{object}\"")]
    UnrecognizedInlineFragment {
        
        object: String,
        
        name: String,
    },
    #[error("Too complex")]
    TooComplex,
    #[error("Too deep")]
    TooDeep,
    #[error("Failed to resolve field: {err}")]
    FieldError {
        err: String,
        extended_error: Option<serde_json::Value>,
    },
    #[error("Entity not found")]
    EntityNotFound,
    #[error("\"__typename\" must be an existing string")]
    TypeNameNotExists,
}
impl QueryError {
    #[doc(hidden)]
    pub fn into_error(self, pos: Pos) -> Error {
        Error::Query {
            pos,
            path: None,
            err: self,
        }
    }
}
#[derive(Debug)]
pub struct RuleError {
    pub locations: Vec<Pos>,
    pub message: String,
}
impl From<ParseError> for Error {
    fn from(err: ParseError) -> Self {
        let msg = err.to_string();
        let mut s = msg.splitn(2, '\n');
        let first = s.next().unwrap();
        let ln = &first[first.rfind(' ').unwrap() + 1..];
        let (line, column) = {
            let mut s = ln.splitn(2, ':');
            (
                s.next().unwrap().parse().unwrap(),
                s.next().unwrap().parse().unwrap(),
            )
        };
        let tail = s.next().unwrap();
        Error::Parse {
            line,
            column,
            message: tail.to_string(),
        }
    }
}
#[allow(missing_docs)]
#[derive(Debug, Error)]
pub enum ParseRequestError {
    #[error("{0}")]
    Io(std::io::Error),
    #[error("Invalid request: {0}")]
    InvalidRequest(serde_json::Error),
    #[error("Invalid files map: {0}")]
    InvalidFilesMap(serde_json::Error),
    #[error("Invalid multipart data: {0}")]
    InvalidMultipart(std::io::Error),
    #[error("Missing \"operators\" part")]
    MissingOperatorsPart,
    #[error("Missing \"map\" part")]
    MissingMapPart,
    #[error("Failed to read part data: {0}")]
    PartData(#[from] std::io::Error),
    #[error("It's not an upload operation")]
    NotUpload,
    #[error("Missing files")]
    MissingFiles,
}
#[allow(missing_docs)]
#[derive(Debug, Error)]
pub enum Error {
    #[error("Parse error: {message}")]
    Parse {
        line: usize,
        column: usize,
        message: String,
    },
    #[error("Query error: {err}")]
    Query {
        pos: Pos,
        path: Option<serde_json::Value>,
        err: QueryError,
    },
    #[error("Rule error")]
    Rule { errors: Vec<RuleError> },
}