import { ApolloLink } from "apollo-boost";
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from "apollo-client";
import { split } from "apollo-link";
import { setContext } from "apollo-link-context";
import { HttpLink } from "apollo-link-http";
import apolloLogger from "apollo-link-logger";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import React, { Component } from "react";
import { ApolloProvider } from "react-apollo";
import SpinnerComponent from "../components/loading-spinner/loading-spinner.component";
//import { shouldRefreshToken, refreshToken } from "../graphql/middleware";
import errorLink from "../graphql/apollo-error-handling";
import App from "./App";

class AppContainer extends Component {
  state = {
    client: null,
    loaded: false
  };
  async componentDidMount() {
    const httpLink = new HttpLink({
      uri: process.env.REACT_APP_GRAPHQL_ENDPOINT
    });

    const wsLink = new WebSocketLink({
      uri: process.env.REACT_APP_GRAPHQL_ENDPOINT_WS,
      options: {
        lazy: true,
        reconnect: true,
        connectionParams: () => {
          const token = localStorage.getItem("token");
          if (token) {
            return {
              headers: {
                authorization: token ? `Bearer ${token}` : ""
              }
            };
          }
        }
      }
    });

    const link = split(
      // split based on operation type
      ({ query }) => {
        const definition = getMainDefinition(query);
        // console.log(
        //   "##Intercepted GQL Transaction : " +
        //     definition.operation +
        //     "|" +
        //     definition.name.value +
        //     "##",
        //   query
        // );
        return (
          definition.kind === "OperationDefinition" &&
          definition.operation === "subscription"
        );
      },
      wsLink,
      httpLink
    );

    const authLink = setContext((_, { headers }) => {
      const token = localStorage.getItem("token");
      if (token) {
        return {
          headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : ""
          }
        };
      } else {
        return { headers };
      }
    });

    const middlewares = [];
    if (process.env.NODE_ENV === "development") {
      middlewares.push(apolloLogger);
    }
    middlewares.push(errorLink.concat(authLink.concat(link)));

    const cache = new InMemoryCache();

    const client = new ApolloClient({
      link: ApolloLink.from(middlewares),
      cache,
      connectToDevTools: true
    });

    this.setState({
      client,
      loaded: true
    });
  }

  componentWillUnmount() {}

  render() {
    const { client, loaded } = this.state;

    if (!loaded) {
      return <SpinnerComponent />;
    }

    return (
      <ApolloProvider client={client}>
        <App />
      </ApolloProvider>
    );
  }
}

export default AppContainer;
