/**
 * @author Steven Fong
 */
// Libraries
import { Map, List, fromJS } from 'immutable';
// Constants
import actionTypes from '../constants/action-types';
import { MENU } from '../constants/menu';

function getChildrenCount(root) {
    if (!root || typeof root !== 'object' || Object.keys(root).length <= 0) {
        return 0;
    }
    return Object.keys(root).reduce((result, next) => {
        let childs = getChildrenCount(root[next]);
        return result + (childs === 0 ? 1 : childs);
    }, 0);
}

function getChildren(root, path) {
    if (!root || typeof root !== 'object' || Object.keys(root).length <= 0) {
        return [];
    }
    return Object.keys(root).map((key) => {
        let newPath = `${path}/${key}`;
        return {
            name: key,
            isCollapsed: true,
            path: newPath,
            children: getChildren(root[key], newPath),
            childrenCount: getChildrenCount(root[key])
        };
    });
}

function enhanceMenu(data) {
    let path = 'root';
    let result = {
        name: 'root',
        isCollapsed: false,
        path,
        children: getChildren(data.root, path),
        childrenCount: getChildrenCount(data.root)
    };
    return result;
}

function updateCollpaseStatus(root, path) {
    if (root.path === path) {
        return {
            ...root,
            isCollapsed: !root.isCollapsed
        };
    }
    if (!root.children || root.children.length === 0) {
        return root;
    }
    let newChildren = root.children.map((child) => updateCollpaseStatus(child, path));

    return {
        ...root,
        children: newChildren
    };
}

const initialState = Map({
  articleList: List.of(),
  articleTotalCount: 0,
  allCategories: enhanceMenu(MENU),
  currentSelectedCategory: Map({}),
  allTags: List.of(),
  allUsers: List.of(),
  allMilestones: List.of(),
});

export default function documentReducer(state = initialState, action) {
  switch (action.type) {
    case actionTypes.FETCH_ARTICLES_SUCCESS:
      return state.set('articleList', action.articleList)
        .set('articleTotalCount', action.count);
    case actionTypes.FETCH_ALL_TAGS_SUCCESS:
      return state.set('allTags', action.allTags);
    case actionTypes.SET_SELECTED_CATEGORY:
      let updatedTree;
      if (action.data && action.data.isLeaf) {
        return state.set('currentSelectedCategory', action.data);
      } else {
        updatedTree = updateCollpaseStatus(state.get('allCategories'), action.data.path);
        return state.set('currentSelectedCategory', action.data).set('allCategories', updatedTree);
      }
    case actionTypes.DELETE_ARTICLE_SUCCESS:
      return state.set('articleList', state.get('articleList').filter(article => {
        return article.id !== action.id;
      }));
    case actionTypes.FETCH_ALL_USERS_SUCCESS:
      return state.set('allUsers', fromJS(action.allUsers));
    case actionTypes.FETCH_ALL_MILESTONES_SUCCESS:
      return state.set('allMilestones', action.allMilestones);
    default:
        return state;
  }
};

@@ -208,239 +208,201 @@
 n ge
-tChildrenCount(root) %7B%0A    if (!root %7C%7C typeof root !== 'object' %7C%7C Object.keys(root).length %3C= 0) %7B%0A        return 0;
+nerateTitleCountMap(articles) %7B%0A    let result = %7B%7D;%0A%0A    articles.forEach((article) =%3E %7B%0A        if (!result%5Barticle.categoryId%5D) %7B
 %0A    
-%7D%0A
+    
     re
-turn Object.keys(root).reduce((result, next) =%3E %7B%0A        let childs = getChildrenCount(root%5Bnext%5D);
+sult%5Barticle.categoryId%5D = 1;%0A        %7D else %7B
 %0A   
@@ -410,62 +410,81 @@
     
-return
+   
  result
- + (childs === 0 ? 1 : childs
+%5Barticle.categoryId%5D += 1;%0A        %7D%0A    %7D
 );%0A
+%0A
     
-%7D, 0)
+return result
 ;%0A%7D%0A
@@ -507,32 +507,47 @@
 ldren(root, path
+, titleCountMap
 ) %7B%0A    if (!roo
@@ -905,34 +905,161 @@
 nt: 
-getChildrenCount(root%5Bkey%5D
+Object.keys(titleCountMap).reduce((acc, title) =%3E %7B%0A                return title.indexOf(newPath) %3E= 0 ? acc + titleCountMap%5Btitle%5D : 0;%0A            %7D, 0
 )%0A  
@@ -1103,16 +1103,31 @@
 enu(data
+, titleCountMap
 ) %7B%0A    
@@ -1143,16 +1143,185 @@
 = 'root'
+,%0A        articlesCount = Object.keys(titleCountMap).reduce((acc, title) =%3E %7B%0A            return title.indexOf(path) %3E= 0 ? acc + titleCountMap%5Btitle%5D : 0;%0A        %7D, 0)
 ;%0A    le
@@ -1442,16 +1442,31 @@
 ot, path
+, titleCountMap
 ),%0A     
@@ -1487,35 +1487,21 @@
 nt: 
-getChildrenCount(data.root)
+articlesCount
 %0A   
@@ -2037,24 +2037,14 @@
 es: 
-enhanceMenu(MENU
+Map(%7B%7D
 ),%0A 
@@ -2156,16 +2156,46 @@
 ),%0A%7D);%0A%0A
+let isFirstTimeFetch = true;%0A%0A
 export d
@@ -2320,32 +2320,172 @@
 TICLES_SUCCESS:%0A
+      if (isFirstTimeFetch) %7B%0A        let newTitleCountMap = generateTitleCountMap(action.articleList);%0A        isFirstTimeFetch = false;%0A  
       return sta
@@ -2534,16 +2534,18 @@
         
+ 
+ 
 .set('ar
@@ -2575,17 +2575,220 @@
 n.count)
-;
+%0A          .set('allCategories', enhanceMenu(MENU, newTitleCountMap));%0A      %7D else %7B%0A        return state.set('articleList', action.articleList)%0A          .set('articleTotalCount', action.count);%0A      %7D
 %0A    cas

Add ocunt