import { GraphQLResolveInfo } from 'graphql';
import { GraphQLClient } from 'graphql-request';
import { print } from 'graphql';
import gql from 'graphql-tag';
export type Maybe<T> = T | null;
export type Exact<T extends { [key: string]: any }> = { [K in keyof T]: T[K] };
export type RequireFields<T, K extends keyof T> = { [X in Exclude<keyof T, K>]?: T[X] } & { [P in K]-?: NonNullable<T[P]> };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export type Pizza = {
  __typename?: 'Pizza';
  id: Scalars['ID'];
  name: Scalars['String'];
  toppings: Array<Topping>;
};

export type Topping = {
  __typename?: 'Topping';
  id: Scalars['ID'];
  name: Scalars['String'];
};

export type Query = {
  __typename?: 'Query';
  getPizzaById: Pizza;
  getToppingById: Topping;
  getPizzaByName: Pizza;
  getToppingByName: Topping;
  listPizza: Array<Maybe<Pizza>>;
  listTopping: Array<Maybe<Topping>>;
};


export type QueryGetPizzaByIdArgs = {
  pizzaId: Scalars['ID'];
};


export type QueryGetToppingByIdArgs = {
  toppingId: Scalars['ID'];
};


export type QueryGetPizzaByNameArgs = {
  pizzaName: Scalars['ID'];
};


export type QueryGetToppingByNameArgs = {
  toppingName: Scalars['ID'];
};

export type ChangePizzaDto = {
  name: Scalars['String'];
  toppingIds: Array<Maybe<Scalars['ID']>>;
};

export type ChangeToppingDto = {
  name: Scalars['String'];
};

export type Mutation = {
  __typename?: 'Mutation';
  createPizza: Pizza;
  updatePizza: Pizza;
  createTopping: Topping;
  updateTopping: Topping;
  deleteTopping: Topping;
  deletePizza: Pizza;
};


export type MutationCreatePizzaArgs = {
  createPizzaDto?: Maybe<ChangePizzaDto>;
};


export type MutationUpdatePizzaArgs = {
  pizzaId: Scalars['ID'];
  updatedPizzaDto: ChangePizzaDto;
};


export type MutationCreateToppingArgs = {
  createToppingDto?: Maybe<ChangeToppingDto>;
};


export type MutationUpdateToppingArgs = {
  toppingId: Scalars['ID'];
  updatedToppingDto: ChangeToppingDto;
};


export type MutationDeleteToppingArgs = {
  toppingId: Scalars['ID'];
};


export type MutationDeletePizzaArgs = {
  pizzaId: Scalars['ID'];
};

export type Subscription = {
  __typename?: 'Subscription';
  pizzasChanged: Array<Maybe<Pizza>>;
  toppingsChanged: Array<Maybe<Topping>>;
};



export type ResolverTypeWrapper<T> = Promise<T> | T;


export type LegacyStitchingResolver<TResult, TParent, TContext, TArgs> = {
  fragment: string;
  resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
};

export type NewStitchingResolver<TResult, TParent, TContext, TArgs> = {
  selectionSet: string;
  resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
};
export type StitchingResolver<TResult, TParent, TContext, TArgs> = LegacyStitchingResolver<TResult, TParent, TContext, TArgs> | NewStitchingResolver<TResult, TParent, TContext, TArgs>;
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
  | ResolverFn<TResult, TParent, TContext, TArgs>
  | StitchingResolver<TResult, TParent, TContext, TArgs>;

export type ResolverFn<TResult, TParent, TContext, TArgs> = (
  parent: TParent,
  args: TArgs,
  context: TContext,
  info: GraphQLResolveInfo
) => Promise<TResult> | TResult;

export type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (
  parent: TParent,
  args: TArgs,
  context: TContext,
  info: GraphQLResolveInfo
) => AsyncIterator<TResult> | Promise<AsyncIterator<TResult>>;

export type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (
  parent: TParent,
  args: TArgs,
  context: TContext,
  info: GraphQLResolveInfo
) => TResult | Promise<TResult>;

export interface SubscriptionSubscriberObject<TResult, TKey extends string, TParent, TContext, TArgs> {
  subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>;
  resolve?: SubscriptionResolveFn<TResult, { [key in TKey]: TResult }, TContext, TArgs>;
}

export interface SubscriptionResolverObject<TResult, TParent, TContext, TArgs> {
  subscribe: SubscriptionSubscribeFn<any, TParent, TContext, TArgs>;
  resolve: SubscriptionResolveFn<TResult, any, TContext, TArgs>;
}

export type SubscriptionObject<TResult, TKey extends string, TParent, TContext, TArgs> =
  | SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
  | SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;

export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
  | ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
  | SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;

export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
  parent: TParent,
  context: TContext,
  info: GraphQLResolveInfo
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;

export type IsTypeOfResolverFn<T = {}> = (obj: T, info: GraphQLResolveInfo) => boolean | Promise<boolean>;

export type NextResolverFn<T> = () => Promise<T>;

export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
  next: NextResolverFn<TResult>,
  parent: TParent,
  args: TArgs,
  context: TContext,
  info: GraphQLResolveInfo
) => TResult | Promise<TResult>;

/** Mapping between all available schema types and the resolvers types */
export type ResolversTypes = {
  Pizza: ResolverTypeWrapper<Pizza>;
  ID: ResolverTypeWrapper<Scalars['ID']>;
  String: ResolverTypeWrapper<Scalars['String']>;
  Topping: ResolverTypeWrapper<Topping>;
  Query: ResolverTypeWrapper<{}>;
  ChangePizzaDto: ChangePizzaDto;
  ChangeToppingDto: ChangeToppingDto;
  Mutation: ResolverTypeWrapper<{}>;
  Subscription: ResolverTypeWrapper<{}>;
  Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
};

/** Mapping between all available schema types and the resolvers parents */
export type ResolversParentTypes = {
  Pizza: Pizza;
  ID: Scalars['ID'];
  String: Scalars['String'];
  Topping: Topping;
  Query: {};
  ChangePizzaDto: ChangePizzaDto;
  ChangeToppingDto: ChangeToppingDto;
  Mutation: {};
  Subscription: {};
  Boolean: Scalars['Boolean'];
};

export type PizzaResolvers<ContextType = any, ParentType extends ResolversParentTypes['Pizza'] = ResolversParentTypes['Pizza']> = {
  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
  name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
  toppings?: Resolver<Array<ResolversTypes['Topping']>, ParentType, ContextType>;
  __isTypeOf?: IsTypeOfResolverFn<ParentType>;
};

export type ToppingResolvers<ContextType = any, ParentType extends ResolversParentTypes['Topping'] = ResolversParentTypes['Topping']> = {
  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
  name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
  __isTypeOf?: IsTypeOfResolverFn<ParentType>;
};

export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
  getPizzaById?: Resolver<ResolversTypes['Pizza'], ParentType, ContextType, RequireFields<QueryGetPizzaByIdArgs, 'pizzaId'>>;
  getToppingById?: Resolver<ResolversTypes['Topping'], ParentType, ContextType, RequireFields<QueryGetToppingByIdArgs, 'toppingId'>>;
  getPizzaByName?: Resolver<ResolversTypes['Pizza'], ParentType, ContextType, RequireFields<QueryGetPizzaByNameArgs, 'pizzaName'>>;
  getToppingByName?: Resolver<ResolversTypes['Topping'], ParentType, ContextType, RequireFields<QueryGetToppingByNameArgs, 'toppingName'>>;
  listPizza?: Resolver<Array<Maybe<ResolversTypes['Pizza']>>, ParentType, ContextType>;
  listTopping?: Resolver<Array<Maybe<ResolversTypes['Topping']>>, ParentType, ContextType>;
};

export type MutationResolvers<ContextType = any, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = {
  createPizza?: Resolver<ResolversTypes['Pizza'], ParentType, ContextType, RequireFields<MutationCreatePizzaArgs, never>>;
  updatePizza?: Resolver<ResolversTypes['Pizza'], ParentType, ContextType, RequireFields<MutationUpdatePizzaArgs, 'pizzaId' | 'updatedPizzaDto'>>;
  createTopping?: Resolver<ResolversTypes['Topping'], ParentType, ContextType, RequireFields<MutationCreateToppingArgs, never>>;
  updateTopping?: Resolver<ResolversTypes['Topping'], ParentType, ContextType, RequireFields<MutationUpdateToppingArgs, 'toppingId' | 'updatedToppingDto'>>;
  deleteTopping?: Resolver<ResolversTypes['Topping'], ParentType, ContextType, RequireFields<MutationDeleteToppingArgs, 'toppingId'>>;
  deletePizza?: Resolver<ResolversTypes['Pizza'], ParentType, ContextType, RequireFields<MutationDeletePizzaArgs, 'pizzaId'>>;
};

export type SubscriptionResolvers<ContextType = any, ParentType extends ResolversParentTypes['Subscription'] = ResolversParentTypes['Subscription']> = {
  pizzasChanged?: SubscriptionResolver<Array<Maybe<ResolversTypes['Pizza']>>, "pizzasChanged", ParentType, ContextType>;
  toppingsChanged?: SubscriptionResolver<Array<Maybe<ResolversTypes['Topping']>>, "toppingsChanged", ParentType, ContextType>;
};

export type Resolvers<ContextType = any> = {
  Pizza?: PizzaResolvers<ContextType>;
  Topping?: ToppingResolvers<ContextType>;
  Query?: QueryResolvers<ContextType>;
  Mutation?: MutationResolvers<ContextType>;
  Subscription?: SubscriptionResolvers<ContextType>;
};


/**
 * @deprecated
 * Use "Resolvers" root object instead. If you wish to get "IResolvers", add "typesPrefix: I" to your config.
 */
export type IResolvers<ContextType = any> = Resolvers<ContextType>;



export type SdkFunctionWrapper = <T>(action: () => Promise<T>) => Promise<T>;


const defaultWrapper: SdkFunctionWrapper = sdkFunction => sdkFunction();
export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = defaultWrapper) {
  return {

  };
}
export type Sdk = ReturnType<typeof getSdk>;
