import * as React from "react"
import { graphql, withApollo, compose } from "react-apollo"
import Stream from "../../Stream"
import Component from "./component"
import { query, badgeQuery, withClearBadge, newNotification } from "./graphql"
const moment = require("moment")
moment.locale("th")

const withData = graphql<any, any, any, any>(query, {
  props: ({ data }) => data && ({
    loading: data.loading,
    refetch: data.refetch,
    notificationBadge: data ? data.notificationBadge : null,
    notifications: data && data.notifications ? data.notifications.nodes : null,
    hasNextPage:
      data && data.notifications ? data.notifications.hasNextPage : null,
    fetchMore: () =>
      data && data.fetchMore({
        variables: {
          after: data.notifications.endCursor
        },
        updateQuery: (previousResult, { fetchMoreResult }) => {
          const newNotifications = fetchMoreResult.notifications
          console.log(
            newNotifications.endCursor,
            previousResult.notifications.endCursor
          )
          if (
            newNotifications.endCursor !==
            previousResult.notifications.endCursor
          ) {
            return {
              ...previousResult,
              notificationBadge: fetchMoreResult.notificationBadge,
              notifications: {
                ...previousResult.notifications,
                endCursor: newNotifications.endCursor,
                hasNextPage: newNotifications.hasNextPage,
                nodes: [].concat(
                  previousResult.notifications.nodes,
                  newNotifications.nodes
                )
              }
            }
          }
        }
      } as any)
  }),
  options: (props) => ({
    context: {
      service: "notification"
    },
    variables: {},
    ssr: false
  })
})

const enhance = compose(withData, withApollo, withClearBadge)

function updateNotificationInfo(client, notifications, badge) {
  const data = client.readQuery({
    query,
    variables: {}
  })
  data.notificationBadge = badge

  if (notifications && notifications.length && data.notifications) {
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < notifications.length; i++) {
      const n: any = notifications[i]
      const node = data.notifications.nodes.find((n2) => n._id === n2._id)
      console.log("will add node", node, n)
      if (!node) {
        data.notifications.nodes = ( [] as any ).concat([n], data.notifications.nodes)
      }
    }
  }
  client.writeQuery({
    query,
    variables: {},
    data
  })
}

class Container extends React.Component<any, any> {
  public onAction = async (action) => {
    try {
      if (action.type === "stream/open") {
        let latestId
        let data = this.props.client.readQuery({
          query,
          variables: {}
        })
        if (!data.notifications) {
          await this.props.refetch()
          data = this.props.client.readQuery({
            query,
            variables: {}
          })
        }
        latestId = data.notifications.nodes.length
          ? data.notifications.nodes[0]._id
          : null
        const result = await this.props.client.query({
          query: newNotification,
          variables: {
            latestId
          },
          context: {
            service: "notification"
          },
          fetchPolicy: "network-only"
        })
        if (result && result.data.newNotifications) {
          updateNotificationInfo(
            this.props.client,
            result.data.newNotifications,
            result.data.notificationBadge
          )
        }
      }
      if (action.type === "notification/insert") {
        const data = this.props.client.readQuery({
          query: badgeQuery
        })
        const addedNotification = Object.assign(
          {
            __typename: "Notification"
          },
          action.payload
        )
        updateNotificationInfo(
          this.props.client,
          [addedNotification],
          data.notificationBadge >= 0 ? data.notificationBadge + 1 : null
        )
      } else if (action.type === "notification/clear-badge-count") {
        updateNotificationInfo(this.props.client, [], 0)
      }
    } catch (error) {
      console.error("apply action error", error)
    }
  }

  public render() {
    return [
      <Component key="0" {...this.props} />,
      <Stream key="1" onAction={this.onAction} url={this.props.streamUrl} />
    ]
  }
}

export default enhance(Container)
