import { createDuck } from 'redux-duck'
import { fromJS, List, Map } from 'immutable'
import { waitForAuth } from './auth';
import gql from '../util/gql'

const COSTY_FIELD_COOLDOWN = 60*1000; // in seconds. query costy fields only 1 time within 60 seconds

const {defineType, createReducer, createAction} = createDuck('articleList');

// Action Types
//

const LOAD = defineType('LOAD');
const LOAD_AUTH_FIELDS = defineType('LOAD_AUTH_FIELDS');

// Action creators
//

let isInCooldown = false;
let lastFilter;
export const load = ({
  filter = 'all',
  orderBy = 'replyRequestCount',
  before, after,
}) => dispatch => {
  if(lastFilter !== filter) {
    // Invalidate costy field cache when filter changes
    isInCooldown = false;
  }

  lastFilter = filter;

  return gql`query(
    $filter: ListArticleFilter,
    $orderBy: [ListArticleOrderBy],
    $before: String,
    $after: String,
  ) {
    ListArticles(
      filter: $filter
      orderBy: $orderBy
      before: $before
      after: $after
      first: 25
    ) {
      edges {
        node {
          id
          text
          replyCount
          replyRequestCount
          createdAt
          references {
            type
          }
        }
        cursor
      }

      ${
        isInCooldown ? '' : /* costy fields */ `
          pageInfo {
            firstCursor
            lastCursor
          }
          totalCount
        `
      }
    }
  }`({
    filter: getFilterObject(filter),
    orderBy: [{[orderBy]: 'DESC'}],
    before,
    after,
  }).then((resp) => {
    // only ignore costy fields on browser.
    //
    if(typeof window !== 'undefined' && !isInCooldown) {
      isInCooldown = true;
      setTimeout(resetCooldown, COSTY_FIELD_COOLDOWN);
    }
    dispatch(createAction(LOAD)(
      resp.getIn(['data', 'ListArticles'], List())
    ));
  });
}

export const loadAuthFields = ({
  filter = 'all',
  orderBy = 'replyRequestCount',
  before, after,
}) => (dispatch, getState) => {
  waitForAuth.then(() => {
    if(!getState().auth.get('user')) return;

    return gql`query(
      $filter: ListArticleFilter,
      $orderBy: [ListArticleOrderBy],
      $before: String,
      $after: String,
    ) {
      ListArticles(
        filter: $filter
        orderBy: $orderBy
        before: $before
        after: $after
        first: 25
      ) {
        edges {
          node {
            id
            requestedForReply
          }
        }
      }
    }`({
      filter: getFilterObject(filter),
      orderBy: [{[orderBy]: 'DESC'}],
      before,
      after,
    }).then((resp) => {
      dispatch(createAction(LOAD_AUTH_FIELDS)(
        resp.getIn(['data', 'ListArticles', 'edges'], List())
      ));
    });
  })
}

// Reducer
//

const initialState = fromJS({
  state: {isLoading: false},
  edges: null,
  firstCursor: null,
  lastCursor: null,
  totalCount: null,
  authFields: {},
});

export default createReducer({
  [LOAD]: (state, {payload}) => state
    .set('edges', payload.get('edges'))
    .set('firstCursor', payload.getIn(['pageInfo', 'firstCursor']) || state.get('firstCursor'))
    .set('lastCursor', payload.getIn(['pageInfo', 'lastCursor']) || state.get('lastCursor'))
    .set('totalCount', payload.get('totalCount') || state.get('totalCount')),
  [LOAD_AUTH_FIELDS]: (state, {payload}) => state
    .set('authFields', Map(payload.map(article => [article.getIn(['node', 'id']), article.get('node')])))
}, initialState);


// Util
//

function resetCooldown() {
  isInCooldown = false;
}

function getFilterObject(filter) {
  if(filter === 'solved') {
    return {replyCount: {GT: 0}};
  } else if(filter === 'unsolved') {
    return {replyCount: {EQ: 0}};
  } else {
    return undefined;
  }
}

@@ -524,24 +524,29 @@
 t load = (%7B%0A
+  q,%0A
   filter = '
@@ -1459,24 +1459,27 @@
 bject(filter
+, q
 ),%0A    order
@@ -1880,16 +1880,21 @@
 ds = (%7B%0A
+  q,%0A
   filter
@@ -2502,16 +2502,19 @@
 t(filter
+, q
 ),%0A     
@@ -3554,20 +3554,127 @@
 t(filter
+, q
 ) %7B%0A
+  const filterObj = %7B%7D;%0A  if(q) %7B%0A    filterObj.moreLikeThis = %7Blike: q, minimumShouldMatch: '0'%7D;%0A  %7D%0A%0A
   if(fil
@@ -3693,32 +3693,34 @@
 ved') %7B%0A    
-return %7B
+filterObj.
 replyCount: 
@@ -3721,17 +3721,18 @@
 ount
-:
+ =
  %7BGT: 0%7D
 %7D;%0A 
@@ -3723,25 +3723,24 @@
 nt = %7BGT: 0%7D
-%7D
 ;%0A  %7D else i
@@ -3774,16 +3774,18 @@
     
-return %7B
+filterObj.
 repl
@@ -3794,17 +3794,18 @@
 ount
-:
+ =
  %7BEQ: 0%7D
 %7D;%0A 
@@ -3800,27 +3800,108 @@
  %7BEQ: 0%7D
-%7D
 ;%0A  %7D
- else
+%0A%0A  // Return filterObj only when it is populated.%0A  if(!Object.keys(filterObj).length)
  %7B%0A    r
@@ -3921,10 +3921,30 @@
 ed;%0A  %7D%0A
+  return filterObj;%0A
 %7D%0A

Support “q” parameter for searching