modules/MainWidget.js

import moment from 'moment';
import mapObject from '../utils/mapObject';
import hasClass from '../utils/hasClass';
import removeClass from '../utils/removeClass';
import objectIterator from '../utils/objectIterator';
import query from '../utils/query';
import closest from '../utils/closest';
import addClass from '../utils/addClass';
import remove from '../utils/remove';
import appendNext from '../utils/appendNext';
import stripHtml from '../utils/stripHtml';

/**
 * MainWidget
 * @param options {Object}
 * @constructor
 */
export const MainWidget = function (options) {
  /**
   * MainWidget settings
   * @memberOf MainWidget
   * @constant
   * @type { Object }
   */
  this.settings = {
    lbWidget: null,
    container: null,
    overlayContainer: null,
    navigation: null,
    section: null,
    detailsContainer: null,
    tournamentListContainer: null,
    headerDate: null,
    labelDate: null,
    preLoader: {
      preLoaderActive: false,
      preLoaderlastAttempt: null,
      preloaderCallbackRecovery: function () {
      }
    },
    achievement: {
      container: null,
      detailsContainer: null
    },
    reward: {
      container: null,
      detailsContainer: null
    },
    messages: {
      container: null,
      detailsContainer: null
    },
    leaderboard: {
      defaultEmptyList: 20,
      topResultSize: 3,
      header: null,
      container: null,
      resultContainer: null,
      list: null,
      topResults: null,
      timerInterval: null
    },
    tournamentsSection: {
      accordionLayout: [{
        label: 'Upcoming Tournaments',
        type: 'readyCompetitions',
        show: false,
        showTopResults: 1
      }, {
        label: 'Active Tournaments',
        type: 'activeCompetitions',
        show: true,
        showTopResults: 1
      }, {
        label: 'Finished Tournaments',
        type: 'finishedCompetitions',
        show: false,
        showTopResults: 1
      }]
    },
    rewardsSection: {
      accordionLayout: [{
        label: 'Available Rewards',
        type: 'availableRewards',
        show: true,
        showTopResults: 1
      }, {
        label: 'Claimed Rewards',
        type: 'rewards',
        show: false,
        showTopResults: 1
      }, {
        label: 'Expired Rewards',
        type: 'expiredRewards',
        show: false,
        showTopResults: 1
      }]
    },
    active: false,
    navigationSwitchLastAtempt: new Date().getTime(),
    navigationSwitchInProgress: false
  };

  if (typeof options !== 'undefined') {
    for (var opt in options) {
      if (options.hasOwnProperty(opt)) {
        this.settings[opt] = options[opt];
      }
    }
  }

  /**
   * Accordion style layout
   * - parameters:
   *      - label: String "Available rewards"
   *      - type: String "available-rewards"
   *      - shown: Boolean true/false
   *
   * @memberOf MainWidget
   * @param data { Array }
   * @param onLayout { Function }
   */
  this.accordionStyle = function (data, onLayout) {
    var _this = this;
    var accordionWrapper = document.createElement('div');

    accordionWrapper.setAttribute('class', 'cl-main-accordion-container');

    mapObject(data, function (entry) {
      var accordionSection = document.createElement('div');
      var accordionLabel = document.createElement('div');
      var topShownEntry = document.createElement('div');
      var accordionListContainer = document.createElement('div');
      var accordionList = document.createElement('div');

      accordionSection.setAttribute('class', 'cl-accordion ' + entry.type + ((typeof entry.show === 'boolean' && entry.show) ? ' cl-shown' : ''));
      accordionLabel.setAttribute('class', 'cl-accordion-label');
      topShownEntry.setAttribute('class', 'cl-accordion-entry');
      accordionListContainer.setAttribute('class', 'cl-accordion-list-container');
      accordionList.setAttribute('class', 'cl-accordion-list');

      if (typeof _this.settings.lbWidget.settings.translation.rewards[entry.type] !== 'undefined') {
        accordionLabel.innerHTML = _this.settings.lbWidget.settings.translation.rewards[entry.type];
      } else if (typeof _this.settings.lbWidget.settings.translation.tournaments[entry.type] !== 'undefined') {
        accordionLabel.innerHTML = _this.settings.lbWidget.settings.translation.tournaments[entry.type];
      } else {
        accordionLabel.innerHTML = entry.label;
      }

      if (typeof onLayout === 'function') {
        onLayout(accordionSection, accordionList, topShownEntry, entry);
      }

      accordionListContainer.appendChild(accordionList);

      accordionSection.appendChild(accordionLabel);
      accordionSection.appendChild(topShownEntry);
      accordionSection.appendChild(accordionListContainer);

      accordionWrapper.appendChild(accordionSection);
    });

    return accordionWrapper;
  };

  this.accordionNavigation = function (element) {
    // var _this = this;
    var parentEl = element.parentNode;

    if (hasClass(parentEl, 'cl-shown')) {
      removeClass(parentEl, 'cl-shown');
    } else {
      objectIterator(query(closest(parentEl, '.cl-main-accordion-container'), '.cl-shown'), function (obj) {
        removeClass(obj, 'cl-shown');
      });

      addClass(parentEl, 'cl-shown');
    }
  };

  this.navigationSorter = function (a, b) {
    if (a.order < b.order) {
      return -1;
    }
    if (a.order > b.order) {
      return 1;
    }
    return 0;
  };

  this.navigationItems = function (container, navigationList) {
    var _this = this;

    // sorting navigation by order number
    navigationList.sort(_this.navigationSorter);

    mapObject(navigationList, function (val, key) {
      var navigationItem = document.createElement('div');
      var navigationItemIcon = document.createElement('div');
      var navigationItemCount = document.createElement('div');

      navigationItem.setAttribute('class', _this.settings.lbWidget.settings.navigation[val.key].navigationClass + ' cl-main-widget-navigation-item' + (_this.settings.lbWidget.settings.navigation[val.key].enable ? '' : ' cl-hidden-navigation-item'));
      navigationItemIcon.setAttribute('class', _this.settings.lbWidget.settings.navigation[val.key].navigationClassIcon + ' cl-main-navigation-item');
      navigationItemCount.setAttribute('class', 'cl-main-navigation-item-count');

      navigationItemIcon.appendChild(navigationItemCount);
      navigationItem.appendChild(navigationItemIcon);
      container.appendChild(navigationItem);
    });
  };

  this.overlayLayout = function () {
    var wrapper = document.createElement('div');

    wrapper.setAttribute('class', 'cl-widget-main-widget-overlay-wrapper');

    return wrapper;
  };

  this.layout = function () {
    var _this = this;
    var wrapper = document.createElement('div');
    var innerWrapper = document.createElement('div');

    var navigationContainer = document.createElement('div');
    var navigationItems = document.createElement('div');

    var mainSectionContainer = document.createElement('div');

    var preLoaderContainer = document.createElement('div');
    var preLoaderContent = document.createElement('div');
    var preLoaderBar1 = document.createElement('div');
    var preLoaderBar2 = document.createElement('div');
    var preLoaderBar3 = document.createElement('div');

    var sectionLB = _this.leaderboardAreaLayout();
    var sectionACH = _this.achievementsAreaLayout();
    var sectionRewards = _this.rewardsAreaLayout();
    var sectionInbox = _this.inboxAreaLayout();

    var navigationItemList = [];
    mapObject(_this.settings.lbWidget.settings.navigation, function (val, key) {
      navigationItemList.push({
        key: key,
        order: parseInt(val.order)
      });
    });

    _this.navigationItems(navigationItems, navigationItemList); // populate sorted navigation

    wrapper.setAttribute('class', 'cl-main-widget-wrapper');
    innerWrapper.setAttribute('class', 'cl-main-widget-inner-wrapper');

    navigationContainer.setAttribute('class', 'cl-main-widget-navigation-container');
    navigationItems.setAttribute('class', 'cl-main-widget-navigation-items');

    mainSectionContainer.setAttribute('class', 'cl-main-widget-section-container' + (_this.settings.lbWidget.settings.showCopyright ? '' : ' cl-hidden-copyright'));

    preLoaderContainer.setAttribute('class', 'cl-main-widget-pre-loader');
    preLoaderContent.setAttribute('class', 'cl-main-widget-pre-loader-content');
    preLoaderBar1.setAttribute('class', 'cl-pre-loader-bar');
    preLoaderBar2.setAttribute('class', 'cl-pre-loader-bar');
    preLoaderBar3.setAttribute('class', 'cl-pre-loader-bar');

    preLoaderContent.appendChild(preLoaderBar1);
    preLoaderContent.appendChild(preLoaderBar2);
    preLoaderContent.appendChild(preLoaderBar3);
    preLoaderContainer.appendChild(preLoaderContent);

    navigationContainer.appendChild(navigationItems);

    mainSectionContainer.appendChild(sectionLB);
    mainSectionContainer.appendChild(sectionACH);
    mainSectionContainer.appendChild(sectionRewards);
    mainSectionContainer.appendChild(sectionInbox);
    mainSectionContainer.appendChild(preLoaderContainer);

    innerWrapper.appendChild(navigationContainer);
    innerWrapper.appendChild(mainSectionContainer);
    wrapper.appendChild(innerWrapper);

    return wrapper;
  };

  this.mainNavigationCheck = function () {
    var _this = this;
    var navItems = query(_this.settings.container, '.cl-main-widget-navigation-item');
    var checkEnabled = 0;

    objectIterator(navItems, function (navItem) {
      if (!hasClass(navItem, 'cl-hidden-navigation-item')) {
        checkEnabled++;
      }
    });

    if (checkEnabled === 1) {
      addClass(query(_this.settings.container, '.cl-main-widget-inner-wrapper'), 'cl-hidden-navigation');
    } else if (checkEnabled === 0) {
      _this.settings.lbWidget.log('All navigation items disabled, check [this.settings.lbWidget.settings.navigation]');
    }
  };

  this.leaderboardAreaLayout = function () {
    var _this = this;
    var sectionLB = document.createElement('div');

    var sectionLBHeader = document.createElement('div');
    var sectionLBHeaderList = document.createElement('div');
    var sectionLBHeaderListIcon = document.createElement('div');
    var sectionLBHeaderLabel = document.createElement('div');
    var sectionLBHeaderDate = document.createElement('div');
    var sectionLBHeaderClose = document.createElement('div');

    var sectionLBDetails = document.createElement('div');
    var sectionLBDetailsInfo = document.createElement('div');
    var sectionLBDetailsInfoIcon = document.createElement('div');
    var sectionLBDetailsImageContainer = document.createElement('div');
    var sectionLBDetailsContentContainer = document.createElement('div');
    var sectionLBDetailsContentContainerLabel = document.createElement('div');
    var sectionLBDetailsContentContainerLabelText = document.createElement('span');
    var sectionLBDetailsContentContainerDate = document.createElement('span');
    var sectionLBDetailsDescriptionContainer = document.createElement('div');
    var sectionLBDetailsDescription = document.createElement('div');
    var sectionLBDetailsDescriptionClose = document.createElement('span');

    var sectionLBLeaderboard = document.createElement('div');
    var sectionLBLeaderboardHeader = document.createElement('div');
    var sectionLBLeaderboardHeaderLabels = document.createElement('div');
    var sectionLBLeaderboardResultsContainer = document.createElement('div');
    var sectionLBLeaderboardHeaderTopResults = document.createElement('div');
    var sectionLBLeaderboardBody = document.createElement('div');
    var sectionLBLeaderboardBodyResults = document.createElement('div');

    var sectionLBMissingMember = document.createElement('div');

    var sectionLBOptInContainer = document.createElement('div');
    var sectionLBOptInAction = document.createElement('a');

    var sectionLBFooter = document.createElement('div');
    var sectionLBFooterContent = document.createElement('div');

    var sectionTournamentDetailsContainer = document.createElement('div');
    var sectionTournamentDetailsHeader = document.createElement('div');
    var sectionTournamentDetailsHeaderLabel = document.createElement('div');
    var sectionTournamentDetailsHeaderDate = document.createElement('div');
    var sectionTournamentDetailsBackBtn = document.createElement('a');
    var sectionTournamentDetailsBodyContainer = document.createElement('div');
    var sectionTournamentDetailsBodyImageContainer = document.createElement('div');
    var sectionTournamentDetailsBody = document.createElement('div');
    var sectionTournamentDetailsOptInContainer = document.createElement('div');
    var sectionTournamentDetailsOptInAction = document.createElement('a');

    var sectionTournamentList = document.createElement('div');
    var sectionTournamentListBody = document.createElement('div');
    var sectionTournamentListBodyResults = document.createElement('div');
    var sectionTournamentBackAction = document.createElement('a');

    sectionLB.setAttribute('class', _this.settings.lbWidget.settings.navigation.tournaments.containerClass + ' cl-main-section-item cl-main-active-section' + (_this.settings.lbWidget.settings.leaderboard.layoutSettings.imageBanner ? ' cl-main-section-image-banner-active' : ''));
    sectionLBHeader.setAttribute('class', 'cl-main-widget-lb-header');
    sectionLBHeaderList.setAttribute('class', 'cl-main-widget-lb-header-list');
    sectionLBHeaderListIcon.setAttribute('class', 'cl-main-widget-lb-header-list-icon');
    sectionLBHeaderLabel.setAttribute('class', 'cl-main-widget-lb-header-label');
    sectionLBHeaderDate.setAttribute('class', 'cl-main-widget-lb-header-date');
    sectionLBHeaderClose.setAttribute('class', 'cl-main-widget-lb-header-close');

    sectionLBDetails.setAttribute('class', 'cl-main-widget-lb-details');
    sectionLBDetailsInfo.setAttribute('class', 'cl-main-widget-lb-details-info');
    sectionLBDetailsInfoIcon.setAttribute('class', 'cl-main-widget-lb-details-info-icon');
    sectionLBDetailsImageContainer.setAttribute('class', 'cl-main-widget-lb-details-image-container');
    sectionLBDetailsContentContainer.setAttribute('class', 'cl-main-widget-lb-details-content');
    sectionLBDetailsContentContainerLabel.setAttribute('class', 'cl-main-widget-lb-details-content-label');
    sectionLBDetailsContentContainerLabelText.setAttribute('class', 'cl-main-widget-lb-details-content-label-text');
    sectionLBDetailsContentContainerDate.setAttribute('class', 'cl-main-widget-lb-details-content-date');
    sectionLBDetailsDescriptionContainer.setAttribute('class', 'cl-main-widget-lb-details-description-container');
    sectionLBDetailsDescription.setAttribute('class', 'cl-main-widget-lb-details-description');
    sectionLBDetailsDescriptionClose.setAttribute('class', 'cl-main-widget-lb-details-description-close');

    // Leaderboard result container
    sectionLBLeaderboard.setAttribute('class', 'cl-main-widget-lb-leaderboard');
    sectionLBLeaderboardHeader.setAttribute('class', 'cl-main-widget-lb-leaderboard-header');
    sectionLBLeaderboardHeaderLabels.setAttribute('class', 'cl-main-widget-lb-leaderboard-header-labels');
    sectionLBLeaderboardResultsContainer.setAttribute('class', 'cl-main-widget-lb-leaderboard-res-container');
    sectionLBLeaderboardHeaderTopResults.setAttribute('class', 'cl-main-widget-lb-leaderboard-header-top-res');
    sectionLBLeaderboardBody.setAttribute('class', 'cl-main-widget-lb-leaderboard-body');
    sectionLBLeaderboardBodyResults.setAttribute('class', 'cl-main-widget-lb-leaderboard-body-res');

    sectionLBMissingMember.setAttribute('class', 'cl-main-widget-lb-missing-member');

    // footer
    sectionLBFooter.setAttribute('class', 'cl-main-widget-lb-footer');
    sectionLBFooterContent.setAttribute('class', 'cl-main-widget-lb-footer-content');

    // details section
    sectionTournamentDetailsContainer.setAttribute('class', 'cl-main-widget-lb-details-container');
    sectionTournamentDetailsHeader.setAttribute('class', 'cl-main-widget-lb-details-header');
    sectionTournamentDetailsHeaderLabel.setAttribute('class', 'cl-main-widget-lb-details-header-label');
    sectionTournamentDetailsHeaderDate.setAttribute('class', 'cl-main-widget-lb-details-header-date');
    sectionTournamentDetailsBackBtn.setAttribute('class', 'cl-main-widget-lb-details-back-btn');
    sectionTournamentDetailsBodyContainer.setAttribute('class', 'cl-main-widget-lb-details-body-container');
    sectionTournamentDetailsBodyImageContainer.setAttribute('class', 'cl-main-widget-lb-details-body-image-cont');
    sectionTournamentDetailsBody.setAttribute('class', 'cl-main-widget-lb-details-body');
    sectionTournamentDetailsOptInContainer.setAttribute('class', 'cl-main-widget-lb-details-optin-container');
    sectionTournamentDetailsOptInAction.setAttribute('class', 'cl-main-widget-lb-details-optin-action');

    sectionTournamentList.setAttribute('class', 'cl-main-widget-tournaments-list');
    sectionTournamentBackAction.setAttribute('class', 'cl-main-widget-tournaments-back-btn');
    sectionTournamentListBody.setAttribute('class', 'cl-main-widget-tournaments-list-body');
    sectionTournamentListBodyResults.setAttribute('class', 'cl-main-widget-tournaments-list-body-res');

    sectionLBOptInContainer.setAttribute('class', 'cl-main-widget-lb-optin-container');
    sectionLBOptInAction.setAttribute('class', 'cl-main-widget-lb-optin-action');

    sectionLBHeaderLabel.innerHTML = _this.settings.lbWidget.settings.translation.tournaments.label;
    sectionLBFooterContent.innerHTML = _this.settings.lbWidget.settings.translation.global.copy;
    sectionTournamentDetailsOptInAction.innerHTML = _this.settings.lbWidget.settings.translation.tournaments.enter;
    sectionTournamentDetailsOptInAction.href = 'javascript:void(0);';
    sectionLBOptInAction.innerHTML = _this.settings.lbWidget.settings.translation.tournaments.enter;
    sectionLBOptInAction.href = 'javascript:void(0);';

    sectionLBHeaderList.appendChild(sectionLBHeaderListIcon);
    sectionLBHeader.appendChild(sectionLBHeaderList);
    sectionLBHeader.appendChild(sectionLBHeaderLabel);
    sectionLBHeader.appendChild(sectionLBHeaderDate);
    sectionLBHeader.appendChild(sectionLBHeaderClose);

    sectionLBDetailsInfo.appendChild(sectionLBDetailsInfoIcon);
    sectionLBDetailsContentContainerLabel.appendChild(sectionLBDetailsContentContainerLabelText);
    sectionLBDetailsContentContainerLabel.appendChild(sectionLBDetailsContentContainerDate);
    sectionLBDetailsContentContainer.appendChild(sectionLBDetailsContentContainerLabel);
    sectionLBDetails.appendChild(sectionLBDetailsInfo);

    if (_this.settings.lbWidget.settings.leaderboard.layoutSettings.imageBanner) {
      sectionLBDetails.appendChild(sectionLBDetailsImageContainer);
    }

    sectionLBDetails.appendChild(sectionLBDetailsContentContainer);

    if (!_this.settings.lbWidget.settings.leaderboard.layoutSettings.titleLinkToDetailsPage) {
      sectionLBDetailsDescriptionContainer.appendChild(sectionLBDetailsDescription);
      sectionLBDetailsDescriptionContainer.appendChild(sectionLBDetailsDescriptionClose);
      sectionLBDetails.appendChild(sectionLBDetailsDescriptionContainer);
    }

    sectionLBLeaderboardHeader.appendChild(sectionLBLeaderboardHeaderLabels);
    sectionLBLeaderboard.appendChild(sectionLBLeaderboardHeader);
    // sectionLBLeaderboard.appendChild(sectionLBLeaderboardHeaderTopResults);
    // sectionLBLeaderboardBody.appendChild(sectionLBLeaderboardBodyResults);
    // sectionLBLeaderboard.appendChild(sectionLBLeaderboardBody);

    sectionLBLeaderboardResultsContainer.appendChild(sectionLBLeaderboardHeaderTopResults);
    sectionLBLeaderboardBody.appendChild(sectionLBLeaderboardBodyResults);
    sectionLBLeaderboardResultsContainer.appendChild(sectionLBLeaderboardBody);
    sectionLBLeaderboard.appendChild(sectionLBLeaderboardResultsContainer);

    sectionLBFooter.appendChild(sectionLBFooterContent);

    sectionTournamentListBody.appendChild(sectionTournamentListBodyResults);
    sectionTournamentList.appendChild(sectionTournamentListBody);
    sectionTournamentList.appendChild(sectionTournamentBackAction);

    sectionTournamentDetailsHeader.appendChild(sectionTournamentDetailsHeaderLabel);
    sectionTournamentDetailsHeader.appendChild(sectionTournamentDetailsHeaderDate);
    sectionTournamentDetailsContainer.appendChild(sectionTournamentDetailsHeader);
    sectionTournamentDetailsContainer.appendChild(sectionTournamentDetailsBackBtn);
    sectionTournamentDetailsBodyContainer.appendChild(sectionTournamentDetailsBodyImageContainer);
    sectionTournamentDetailsBodyContainer.appendChild(sectionTournamentDetailsBody);
    sectionTournamentDetailsContainer.appendChild(sectionTournamentDetailsBodyContainer);
    sectionTournamentDetailsOptInContainer.appendChild(sectionTournamentDetailsOptInAction);
    sectionTournamentDetailsContainer.appendChild(sectionTournamentDetailsOptInContainer);

    sectionLBOptInContainer.appendChild(sectionLBOptInAction);

    sectionLB.appendChild(sectionLBHeader);
    sectionLB.appendChild(sectionLBDetails);
    sectionLB.appendChild(sectionLBLeaderboard);
    sectionLB.appendChild(sectionLBMissingMember);
    sectionLB.appendChild(sectionLBOptInContainer);
    sectionLB.appendChild(sectionLBFooter);
    sectionLB.appendChild(sectionTournamentDetailsContainer);
    sectionLB.appendChild(sectionTournamentList);

    return sectionLB;
  };

  this.achievementsAreaLayout = function () {
    var _this = this;
    var sectionACH = document.createElement('div');

    var sectionACHHeader = document.createElement('div');
    var sectionACHHeaderLabel = document.createElement('div');
    var sectionACHHeaderDate = document.createElement('div');
    var sectionACHHeaderClose = document.createElement('div');

    var sectionACHDetails = document.createElement('div');
    var sectionACHDetailsInfo = document.createElement('div');
    var sectionACHDetailsInfoIcon = document.createElement('div');
    var sectionACHDetailsContentContainer = document.createElement('div');
    var sectionACHDetailsContentContainerLabel = document.createElement('div');
    var sectionACHDetailsContentContainerDate = document.createElement('div');

    var sectionACHList = document.createElement('div');
    var sectionACHListBody = document.createElement('div');
    var sectionACHListBodyResults = document.createElement('div');

    var sectionACHFooter = document.createElement('div');
    var sectionACHFooterContent = document.createElement('div');

    var sectionAchievementDetailsContainer = document.createElement('div');
    var sectionAchievementDetailsHeader = document.createElement('div');
    var sectionAchievementDetailsHeaderLabel = document.createElement('div');
    var sectionAchievementDetailsHeaderDate = document.createElement('div');
    var sectionAchievementDetailsBackBtn = document.createElement('a');
    var sectionAchievementDetailsBodyContainer = document.createElement('div');
    var sectionAchievementDetailsBodyImageContainer = document.createElement('div');
    var sectionAchievementDetailsBody = document.createElement('div');

    sectionACH.setAttribute('class', _this.settings.lbWidget.settings.navigation.achievements.containerClass + ' cl-main-section-item');
    sectionACHHeader.setAttribute('class', 'cl-main-widget-ach-header');
    sectionACHHeaderLabel.setAttribute('class', 'cl-main-widget-ach-header-label');
    sectionACHHeaderDate.setAttribute('class', 'cl-main-widget-ach-header-date');
    sectionACHHeaderClose.setAttribute('class', 'cl-main-widget-ach-header-close');

    sectionACHDetails.setAttribute('class', 'cl-main-widget-ach-details');
    sectionACHDetailsInfo.setAttribute('class', 'cl-main-widget-ach-details-info');
    sectionACHDetailsInfoIcon.setAttribute('class', 'cl-main-widget-ach-details-info-icon');
    sectionACHDetailsContentContainer.setAttribute('class', 'cl-main-widget-ach-details-content');
    sectionACHDetailsContentContainerLabel.setAttribute('class', 'cl-main-widget-ach-details-content-label');
    sectionACHDetailsContentContainerDate.setAttribute('class', 'cl-main-widget-ach-details-content-date');

    // Leaderboard result container
    sectionACHList.setAttribute('class', 'cl-main-widget-ach-list');
    sectionACHListBody.setAttribute('class', 'cl-main-widget-ach-list-body');
    sectionACHListBodyResults.setAttribute('class', 'cl-main-widget-ach-list-body-res');

    // footer
    sectionACHFooter.setAttribute('class', 'cl-main-widget-ach-footer');
    sectionACHFooterContent.setAttribute('class', 'cl-main-widget-ach-footer-content');

    // details section
    sectionAchievementDetailsContainer.setAttribute('class', 'cl-main-widget-ach-details-container');
    sectionAchievementDetailsHeader.setAttribute('class', 'cl-main-widget-ach-details-header');
    sectionAchievementDetailsHeaderLabel.setAttribute('class', 'cl-main-widget-ach-details-header-label');
    sectionAchievementDetailsHeaderDate.setAttribute('class', 'cl-main-widget-ach-details-header-date');
    sectionAchievementDetailsBackBtn.setAttribute('class', 'cl-main-widget-ach-details-back-btn');
    sectionAchievementDetailsBodyContainer.setAttribute('class', 'cl-main-widget-ach-details-body-container');
    sectionAchievementDetailsBodyImageContainer.setAttribute('class', 'cl-main-widget-ach-details-body-image-cont');
    sectionAchievementDetailsBody.setAttribute('class', 'cl-main-widget-ach-details-body');

    sectionACHHeaderLabel.innerHTML = _this.settings.lbWidget.settings.translation.achievements.label;
    sectionACHFooterContent.innerHTML = _this.settings.lbWidget.settings.translation.global.copy;

    sectionAchievementDetailsHeader.appendChild(sectionAchievementDetailsHeaderLabel);
    sectionAchievementDetailsHeader.appendChild(sectionAchievementDetailsHeaderDate);
    sectionAchievementDetailsContainer.appendChild(sectionAchievementDetailsHeader);
    sectionAchievementDetailsContainer.appendChild(sectionAchievementDetailsBackBtn);
    sectionAchievementDetailsBodyContainer.appendChild(sectionAchievementDetailsBodyImageContainer);
    sectionAchievementDetailsBodyContainer.appendChild(sectionAchievementDetailsBody);
    sectionAchievementDetailsContainer.appendChild(sectionAchievementDetailsBodyContainer);

    sectionACHHeader.appendChild(sectionACHHeaderLabel);
    sectionACHHeader.appendChild(sectionACHHeaderDate);
    sectionACHHeader.appendChild(sectionACHHeaderClose);

    sectionACHDetailsInfo.appendChild(sectionACHDetailsInfoIcon);
    sectionACHDetailsContentContainer.appendChild(sectionACHDetailsContentContainerLabel);
    sectionACHDetailsContentContainer.appendChild(sectionACHDetailsContentContainerDate);
    sectionACHDetails.appendChild(sectionACHDetailsInfo);
    sectionACHDetails.appendChild(sectionACHDetailsContentContainer);

    sectionACHListBody.appendChild(sectionACHListBodyResults);
    sectionACHList.appendChild(sectionACHListBody);

    sectionACHFooter.appendChild(sectionACHFooterContent);

    sectionACH.appendChild(sectionACHHeader);
    sectionACH.appendChild(sectionACHDetails);
    sectionACH.appendChild(sectionACHList);
    sectionACH.appendChild(sectionACHFooter);
    sectionACH.appendChild(sectionAchievementDetailsContainer);

    return sectionACH;
  };

  this.rewardsAreaLayout = function () {
    var _this = this;
    var sectionRewards = document.createElement('div');

    var sectionRewardsHeader = document.createElement('div');
    var sectionRewardsHeaderLabel = document.createElement('div');
    var sectionRewardsHeaderDate = document.createElement('div');
    var sectionRewardsHeaderClose = document.createElement('div');

    var sectionRewardsDetails = document.createElement('div');
    var sectionRewardsDetailsInfo = document.createElement('div');
    var sectionRewardsDetailsInfoIcon = document.createElement('div');
    var sectionRewardsDetailsContentContainer = document.createElement('div');
    var sectionRewardsDetailsContentContainerLabel = document.createElement('div');
    var sectionRewardsDetailsContentContainerDate = document.createElement('div');

    var sectionRewardsList = document.createElement('div');
    var sectionRewardsListBody = document.createElement('div');
    var sectionRewardsListBodyResults = document.createElement('div');

    var sectionRewardsFooter = document.createElement('div');
    var sectionRewardsFooterContent = document.createElement('div');

    var sectionRewardsDetailsContainer = document.createElement('div');
    var sectionRewardsDetailsHeader = document.createElement('div');
    var sectionRewardsDetailsHeaderLabel = document.createElement('div');
    var sectionRewardsDetailsHeaderDate = document.createElement('div');
    var sectionRewardsDetailsBackBtn = document.createElement('a');
    var sectionRewardsDetailsBodyContainer = document.createElement('div');
    var sectionRewardsDetailsBodyImageContainer = document.createElement('div');
    var sectionRewardsDetailsBody = document.createElement('div');
    var sectionRewardsWinningsContainer = document.createElement('div');
    var sectionRewardsWinningsIcon = document.createElement('div');
    var sectionRewardsWinningsValue = document.createElement('div');
    var sectionRewardsClaimContainer = document.createElement('div');
    var sectionRewardsClaimBtn = document.createElement('a');

    sectionRewards.setAttribute('class', _this.settings.lbWidget.settings.navigation.rewards.containerClass + ' cl-main-section-item');
    sectionRewardsHeader.setAttribute('class', 'cl-main-widget-reward-header');
    sectionRewardsHeaderLabel.setAttribute('class', 'cl-main-widget-reward-header-label');
    sectionRewardsHeaderDate.setAttribute('class', 'cl-main-widget-reward-header-date');
    sectionRewardsHeaderClose.setAttribute('class', 'cl-main-widget-reward-header-close');

    sectionRewardsDetails.setAttribute('class', 'cl-main-widget-reward-details');
    sectionRewardsDetailsInfo.setAttribute('class', 'cl-main-widget-reward-details-info');
    sectionRewardsDetailsInfoIcon.setAttribute('class', 'cl-main-widget-reward-details-info-icon');
    sectionRewardsDetailsContentContainer.setAttribute('class', 'cl-main-widget-reward-details-content');
    sectionRewardsDetailsContentContainerLabel.setAttribute('class', 'cl-main-widget-reward-details-content-label');
    sectionRewardsDetailsContentContainerDate.setAttribute('class', 'cl-main-widget-reward-details-content-date');

    // Leaderboard result container
    sectionRewardsList.setAttribute('class', 'cl-main-widget-reward-list');
    sectionRewardsListBody.setAttribute('class', 'cl-main-widget-reward-list-body');
    sectionRewardsListBodyResults.setAttribute('class', 'cl-main-widget-reward-list-body-res');

    // footer
    sectionRewardsFooter.setAttribute('class', 'cl-main-widget-reward-footer');
    sectionRewardsFooterContent.setAttribute('class', 'cl-main-widget-reward-footer-content');

    // details section
    sectionRewardsDetailsContainer.setAttribute('class', 'cl-main-widget-reward-details-container');
    sectionRewardsDetailsHeader.setAttribute('class', 'cl-main-widget-reward-details-header');
    sectionRewardsDetailsHeaderLabel.setAttribute('class', 'cl-main-widget-reward-details-header-label');
    sectionRewardsDetailsHeaderDate.setAttribute('class', 'cl-main-widget-reward-details-header-date');
    sectionRewardsDetailsBackBtn.setAttribute('class', 'cl-main-widget-reward-details-back-btn');
    sectionRewardsDetailsBodyContainer.setAttribute('class', 'cl-main-widget-reward-details-body-container');
    sectionRewardsDetailsBodyImageContainer.setAttribute('class', 'cl-main-widget-reward-details-body-image-cont');
    sectionRewardsDetailsBody.setAttribute('class', 'cl-main-widget-reward-details-body');
    sectionRewardsWinningsContainer.setAttribute('class', 'cl-main-widget-reward-winnings-container');
    sectionRewardsWinningsIcon.setAttribute('class', 'cl-main-widget-reward-winnings-icon');
    sectionRewardsWinningsValue.setAttribute('class', 'cl-main-widget-reward-winnings-value');
    sectionRewardsClaimContainer.setAttribute('class', 'cl-main-widget-reward-claim-container');
    sectionRewardsClaimBtn.setAttribute('class', 'cl-main-widget-reward-claim-btn');

    sectionRewardsHeaderLabel.innerHTML = _this.settings.lbWidget.settings.translation.rewards.label;
    sectionRewardsFooterContent.innerHTML = _this.settings.lbWidget.settings.translation.global.copy;
    sectionRewardsClaimBtn.innerHTML = _this.settings.lbWidget.settings.translation.rewards.claim;

    sectionRewardsWinningsContainer.appendChild(sectionRewardsWinningsIcon);
    sectionRewardsWinningsContainer.appendChild(sectionRewardsWinningsValue);
    sectionRewardsClaimContainer.appendChild(sectionRewardsClaimBtn);

    sectionRewardsDetailsHeader.appendChild(sectionRewardsDetailsHeaderLabel);
    sectionRewardsDetailsHeader.appendChild(sectionRewardsDetailsHeaderDate);
    sectionRewardsDetailsContainer.appendChild(sectionRewardsDetailsHeader);
    sectionRewardsDetailsContainer.appendChild(sectionRewardsDetailsBackBtn);
    sectionRewardsDetailsBodyContainer.appendChild(sectionRewardsDetailsBodyImageContainer);
    sectionRewardsDetailsBodyContainer.appendChild(sectionRewardsDetailsBody);
    sectionRewardsDetailsBodyContainer.appendChild(sectionRewardsWinningsContainer);
    sectionRewardsDetailsContainer.appendChild(sectionRewardsDetailsBodyContainer);
    sectionRewardsDetailsContainer.appendChild(sectionRewardsClaimContainer);

    sectionRewardsHeader.appendChild(sectionRewardsHeaderLabel);
    sectionRewardsHeader.appendChild(sectionRewardsHeaderDate);
    sectionRewardsHeader.appendChild(sectionRewardsHeaderClose);

    sectionRewardsDetailsInfo.appendChild(sectionRewardsDetailsInfoIcon);
    sectionRewardsDetailsContentContainer.appendChild(sectionRewardsDetailsContentContainerLabel);
    sectionRewardsDetailsContentContainer.appendChild(sectionRewardsDetailsContentContainerDate);
    sectionRewardsDetails.appendChild(sectionRewardsDetailsInfo);
    sectionRewardsDetails.appendChild(sectionRewardsDetailsContentContainer);

    sectionRewardsListBody.appendChild(sectionRewardsListBodyResults);
    sectionRewardsList.appendChild(sectionRewardsListBody);

    sectionRewardsFooter.appendChild(sectionRewardsFooterContent);

    sectionRewards.appendChild(sectionRewardsHeader);
    sectionRewards.appendChild(sectionRewardsDetails);
    sectionRewards.appendChild(sectionRewardsList);
    sectionRewards.appendChild(sectionRewardsFooter);
    sectionRewards.appendChild(sectionRewardsDetailsContainer);

    return sectionRewards;
  };

  this.inboxAreaLayout = function () {
    var _this = this;
    var sectionInbox = document.createElement('div');

    var sectionInboxHeader = document.createElement('div');
    var sectionInboxHeaderLabel = document.createElement('div');
    var sectionInboxHeaderDate = document.createElement('div');
    var sectionInboxHeaderClose = document.createElement('div');

    var sectionInboxDetails = document.createElement('div');
    var sectionInboxDetailsInfo = document.createElement('div');
    var sectionInboxDetailsInfoIcon = document.createElement('div');
    var sectionInboxDetailsContentContainer = document.createElement('div');
    var sectionInboxDetailsContentContainerLabel = document.createElement('div');
    var sectionInboxDetailsContentContainerDate = document.createElement('div');

    var sectionInboxList = document.createElement('div');
    var sectionInboxListBody = document.createElement('div');
    var sectionInboxListBodyResults = document.createElement('div');

    var sectionInboxFooter = document.createElement('div');
    var sectionInboxFooterContent = document.createElement('div');

    var sectionInboxDetailsContainer = document.createElement('div');
    var sectionInboxDetailsHeader = document.createElement('div');
    var sectionInboxDetailsHeaderLabel = document.createElement('div');
    var sectionInboxDetailsHeaderDate = document.createElement('div');
    var sectionInboxDetailsBackBtn = document.createElement('a');
    var sectionInboxDetailsBodyContainer = document.createElement('div');
    var sectionInboxDetailsBody = document.createElement('div');

    sectionInbox.setAttribute('class', _this.settings.lbWidget.settings.navigation.inbox.containerClass + ' cl-main-section-item');
    sectionInboxHeader.setAttribute('class', 'cl-main-widget-inbox-header');
    sectionInboxHeaderLabel.setAttribute('class', 'cl-main-widget-inbox-header-label');
    sectionInboxHeaderDate.setAttribute('class', 'cl-main-widget-inbox-header-date');
    sectionInboxHeaderClose.setAttribute('class', 'cl-main-widget-inbox-header-close');

    sectionInboxDetails.setAttribute('class', 'cl-main-widget-inbox-details');
    sectionInboxDetailsInfo.setAttribute('class', 'cl-main-widget-inbox-details-info');
    sectionInboxDetailsInfoIcon.setAttribute('class', 'cl-main-widget-inbox-details-info-icon');
    sectionInboxDetailsContentContainer.setAttribute('class', 'cl-main-widget-inbox-details-content');
    sectionInboxDetailsContentContainerLabel.setAttribute('class', 'cl-main-widget-inbox-details-content-label');
    sectionInboxDetailsContentContainerDate.setAttribute('class', 'cl-main-widget-inbox-details-content-date');

    // Leaderboard result container
    sectionInboxList.setAttribute('class', 'cl-main-widget-inbox-list');
    sectionInboxListBody.setAttribute('class', 'cl-main-widget-inbox-list-body');
    sectionInboxListBodyResults.setAttribute('class', 'cl-main-widget-inbox-list-body-res');

    // footer
    sectionInboxFooter.setAttribute('class', 'cl-main-widget-inbox-footer');
    sectionInboxFooterContent.setAttribute('class', 'cl-main-widget-inbox-footer-content');

    // details section
    sectionInboxDetailsContainer.setAttribute('class', 'cl-main-widget-inbox-details-container');
    sectionInboxDetailsHeader.setAttribute('class', 'cl-main-widget-inbox-details-header');
    sectionInboxDetailsHeaderLabel.setAttribute('class', 'cl-main-widget-inbox-details-header-label');
    sectionInboxDetailsHeaderDate.setAttribute('class', 'cl-main-widget-inbox-details-header-date');
    sectionInboxDetailsBackBtn.setAttribute('class', 'cl-main-widget-inbox-details-back-btn');
    sectionInboxDetailsBodyContainer.setAttribute('class', 'cl-main-widget-inbox-details-body-container');
    sectionInboxDetailsBody.setAttribute('class', 'cl-main-widget-inbox-details-body');

    sectionInboxHeaderLabel.innerHTML = _this.settings.lbWidget.settings.translation.messages.label;
    sectionInboxFooterContent.innerHTML = _this.settings.lbWidget.settings.translation.global.copy;

    sectionInboxHeader.appendChild(sectionInboxHeaderLabel);
    sectionInboxHeader.appendChild(sectionInboxHeaderDate);
    sectionInboxHeader.appendChild(sectionInboxHeaderClose);

    sectionInboxDetailsInfo.appendChild(sectionInboxDetailsInfoIcon);
    sectionInboxDetailsContentContainer.appendChild(sectionInboxDetailsContentContainerLabel);
    sectionInboxDetailsContentContainer.appendChild(sectionInboxDetailsContentContainerDate);
    sectionInboxDetails.appendChild(sectionInboxDetailsInfo);
    sectionInboxDetails.appendChild(sectionInboxDetailsContentContainer);

    sectionInboxListBody.appendChild(sectionInboxListBodyResults);
    sectionInboxList.appendChild(sectionInboxListBody);

    sectionInboxDetailsHeader.appendChild(sectionInboxDetailsHeaderLabel);
    sectionInboxDetailsHeader.appendChild(sectionInboxDetailsHeaderDate);
    sectionInboxDetailsContainer.appendChild(sectionInboxDetailsHeader);
    sectionInboxDetailsContainer.appendChild(sectionInboxDetailsBackBtn);
    sectionInboxDetailsBodyContainer.appendChild(sectionInboxDetailsBody);
    sectionInboxDetailsContainer.appendChild(sectionInboxDetailsBodyContainer);

    sectionInboxFooter.appendChild(sectionInboxFooterContent);

    sectionInbox.appendChild(sectionInboxHeader);
    sectionInbox.appendChild(sectionInboxDetails);
    sectionInbox.appendChild(sectionInboxList);
    sectionInbox.appendChild(sectionInboxFooter);
    sectionInbox.appendChild(sectionInboxDetailsContainer);

    return sectionInbox;
  };

  this.leaderboardHeader = function () {
    var _this = this;
    var rankCol = document.createElement('div');
    var iconCol = document.createElement('div');
    var nameCol = document.createElement('div');
    var growthCol = document.createElement('div');
    var pointsCol = document.createElement('div');

    rankCol.setAttribute('class', 'cl-rank-col cl-col');
    iconCol.setAttribute('class', 'cl-icon-col cl-col');
    nameCol.setAttribute('class', 'cl-name-col cl-col');
    growthCol.setAttribute('class', 'cl-growth-col cl-col');
    pointsCol.setAttribute('class', 'cl-points-col cl-col');

    rankCol.innerHTML = _this.settings.lbWidget.settings.translation.leaderboard.rank;
    iconCol.innerHTML = '';
    nameCol.innerHTML = _this.settings.lbWidget.settings.translation.leaderboard.name;
    growthCol.innerHTML = '';
    pointsCol.innerHTML = _this.settings.lbWidget.settings.translation.leaderboard.points;

    _this.settings.leaderboard.header.appendChild(rankCol);
    _this.settings.leaderboard.header.appendChild(iconCol);
    _this.settings.leaderboard.header.appendChild(nameCol);
    _this.settings.leaderboard.header.appendChild(growthCol);
    _this.settings.leaderboard.header.appendChild(pointsCol);

    var rewardCol = document.createElement('div');
    var rewardEnabled = (typeof _this.settings.lbWidget.settings.competition.activeContest !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest !== null && typeof _this.settings.lbWidget.settings.competition.activeContest.rewards !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest.rewards.length > 0);
    rewardCol.setAttribute('class', 'cl-reward-col cl-col' + (rewardEnabled ? ' cl-col-reward-enabled' : ''));
    rewardCol.innerHTML = _this.settings.lbWidget.settings.translation.leaderboard.prize;

    addClass(_this.settings.leaderboard.header, 'cl-reward-enabled');

    _this.settings.leaderboard.header.appendChild(rewardCol);
  };

  this.leaderboardRow = function (rank, icon, name, change, growth, points, reward, count, memberFound) {
    var _this = this;
    var cellWrapper = document.createElement('div');
    var rankCel = document.createElement('div');
    var rankCelValue = document.createElement('div');
    var iconCel = document.createElement('div');
    var iconCelImg = new Image();
    var nameCel = document.createElement('div');
    var growthCel = document.createElement('div');
    var pointsCel = document.createElement('div');
    var memberFoundClass = (memberFound) ? ' cl-lb-member-row' : '';

    cellWrapper.setAttribute('class', 'cl-lb-row cl-lb-rank-' + rank + ' cl-lb-count-' + count + memberFoundClass);
    rankCel.setAttribute('class', 'cl-rank-col cl-col cl-rank-' + rank);
    rankCelValue.setAttribute('class', 'cl-rank-col-value');
    iconCel.setAttribute('class', 'cl-icon-col cl-col');
    iconCelImg.setAttribute('class', 'cl-icon-col-img');
    nameCel.setAttribute('class', 'cl-name-col cl-col');
    growthCel.setAttribute('class', 'cl-growth-col cl-col');
    pointsCel.setAttribute('class', 'cl-points-col cl-col');

    cellWrapper.dataset.rank = rank;

    rankCelValue.innerHTML = rank;
    nameCel.innerHTML = name;
    growthCel.dataset.growth = (change < 0) ? 'down' : (change > 0 ? 'up' : 'same');
    growthCel.dataset.change = change;
    growthCel.innerHTML = growth;
    pointsCel.innerHTML = points;

    if (icon.length > 0) {
      iconCelImg.src = icon;
      iconCelImg.alt = name;
    } else {
      iconCelImg.style.display = 'none';
    }

    rankCel.appendChild(rankCelValue);
    cellWrapper.appendChild(rankCel);
    iconCel.appendChild(iconCelImg);
    cellWrapper.appendChild(iconCel);
    cellWrapper.appendChild(nameCel);
    cellWrapper.appendChild(growthCel);
    cellWrapper.appendChild(pointsCel);

    var rewardCel = document.createElement('div');
    var rewardEnabled = (typeof _this.settings.lbWidget.settings.competition.activeContest !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest !== null && typeof _this.settings.lbWidget.settings.competition.activeContest.rewards !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest.rewards.length > 0);
    rewardCel.setAttribute('class', 'cl-reward-col cl-col' + (rewardEnabled ? ' cl-col-reward-enabled' : ''));
    rewardCel.innerHTML = (typeof reward !== 'undefined' && reward !== null) ? reward : '';

    addClass(cellWrapper, 'cl-reward-enabled');

    cellWrapper.appendChild(rewardCel);

    return cellWrapper;
  };

  this.leaderboardRowUpdate = function (rank, icon, name, change, growth, points, reward, count, memberFound, onMissing) {
    var _this = this;
    var cellRow = query(_this.settings.leaderboard.container, '.cl-lb-rank-' + rank + '.cl-lb-count-' + count);

    if (cellRow === null) {
      onMissing(rank, icon, name, change, growth, points, reward, count, memberFound);
    } else {
      var rankCel = query(cellRow, '.cl-rank-col-value');
      var iconCel = query(cellRow, '.cl-icon-col-img');
      var nameCel = query(cellRow, '.cl-name-col');
      var growthCel = query(cellRow, '.cl-growth-col');
      var pointsCel = query(cellRow, '.cl-points-col');
      var memberFoundClass = 'cl-lb-member-row';
      var rowHasClass = hasClass(cellRow, memberFoundClass);

      if (count > 0 && !hasClass(cellRow, 'cl-shared-rank')) {
        addClass(cellRow, 'cl-shared-rank');
      }

      if (memberFound && !rowHasClass) {
        addClass(cellRow, memberFoundClass);
      } else if (!memberFound && rowHasClass) {
        removeClass(cellRow, memberFoundClass);
      }

      cellRow.dataset.rank = rank;

      rankCel.innerHTML = rank;
      nameCel.innerHTML = name;

      growthCel.dataset.growth = (change < 0) ? 'down' : (change > 0 ? 'up' : 'same');
      growthCel.dataset.change = change;
      growthCel.innerHTML = growth;

      pointsCel.innerHTML = points;

      if (icon.length > 0) {
        iconCel.src = icon;
        iconCel.alt = name;
        iconCel.style.display = 'block';
      } else {
        iconCel.style.display = 'none';
      }

      if (typeof _this.settings.lbWidget.settings.competition.activeContest !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest !== null && typeof _this.settings.lbWidget.settings.competition.activeContest.rewards !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest.rewards.length > 0) {
        var rewardCel = query(cellRow, '.cl-reward-col');
        if (rewardCel !== null) {
          rewardCel.innerHTML = (typeof reward !== 'undefined' && reward !== null) ? reward : '';
        }
      }
    }
  };

  this.populateLeaderboardResultsWithDefaultEntries = function () {
    var _this = this;
    var topResults = [];
    var remainingResults = [];

    for (let i = 0; i < _this.settings.leaderboard.topResultSize; i++) {
      const rank = i + 1;

      topResults.push({
        name: '--',
        rank: rank,
        points: '--',
        memberId: '',
        memberRefId: ''
      });
    }

    for (let s = _this.settings.leaderboard.topResultSize; s < _this.settings.leaderboard.defaultEmptyList; s++) {
      const rank = s + 1;

      remainingResults.push({
        name: '--',
        rank: rank,
        points: '--',
        memberId: '',
        memberRefId: ''
      });
    }

    _this.updateLeaderboardTopResults(topResults);
    _this.updateLeaderboardResults(remainingResults);
  };

  this.updateLeaderboardTopResults = function (topResults) {
    var _this = this;
    var rankCheck = [];
    var cleanupRankCheck = [];

    // cleanup
    mapObject(topResults, function (lb) {
      cleanupRankCheck.push(lb.rank);
      objectIterator(query(_this.settings.leaderboard.topResults, '.cl-lb-rank-' + lb.rank + '.cl-shared-rank'), function (obj) {
        remove(obj);
      });
    });

    objectIterator(query(_this.settings.leaderboard.topResults, '.cl-lb-row'), function (obj) {
      var rank = parseInt(obj.dataset.rank);
      if (cleanupRankCheck.indexOf(rank) === -1 && rank > _this.settings.leaderboard.defaultEmptyList) {
        remove(obj);
      }
    });

    mapObject(topResults, function (lb) {
      var count = 0;
      var icon = _this.settings.lbWidget.populateIdenticonBase64Image(lb.memberId);
      var memberFound = (_this.settings.lbWidget.settings.memberId === lb.memberId || _this.settings.lbWidget.settings.memberId === lb.memberRefId);
      var memberName = (memberFound) ? _this.settings.lbWidget.settings.translation.leaderboard.you : lb.name;
      var reward = _this.getReward(lb.rank);
      var change = (typeof lb.change === 'undefined') ? 0 : lb.change;
      var growthType = (change < 0) ? 'down' : (change > 0 ? 'up' : 'same');
      var growthIcon = "<span class='cl-growth-icon cl-growth-" + growthType + "'></span>";
      var formattedPoints = _this.settings.lbWidget.settings.leaderboard.pointsFormatter(lb.points);

      if (rankCheck.indexOf(lb.rank) !== -1) {
        for (var rc = 0; rc < rankCheck.length; rc++) {
          if (lb.rank === rankCheck[rc]) {
            count++;
          }
        }
      }

      _this.leaderboardRowUpdate(
        lb.rank,
        icon, // icon
        memberName,
        change,
        growthIcon, // growth
        formattedPoints,
        reward, // reward
        count,
        memberFound,
        function (rank, icon, name, change, growth, points, reward, count, memberFound) {
          var newRow = _this.leaderboardRow(rank, icon, name, change, growth, points, reward, count, memberFound);
          var prevCellRow = query(_this.settings.leaderboard.container, '.cl-lb-rank-' + rank + '.cl-lb-count-' + (count - 1));

          if (prevCellRow !== null && typeof prevCellRow.length === 'undefined') {
            appendNext(prevCellRow, newRow);
          } else {
            _this.settings.leaderboard.topResults.appendChild(newRow);
          }
        }
      );

      rankCheck.push(lb.rank);
    });
  };

  this.getReward = function (rank) {
    var _this = this;
    var rewardResponse = [];

    if (typeof _this.settings.lbWidget.settings.competition.activeContest !== 'undefined' && _this.settings.lbWidget.settings.competition.activeContest !== null) {
      mapObject(_this.settings.lbWidget.settings.competition.activeContest.rewards, function (reward) {
        if (reward.rewardRank instanceof Array && reward.rewardRank.indexOf(rank) !== -1) {
          rewardResponse.push(_this.settings.lbWidget.settings.partialFunctions.rewardFormatter(reward));
        }
      });
    }

    return rewardResponse.join(', ');
  };

  this.updateLeaderboardResults = function (remainingResults) {
    var _this = this;
    var rankCheck = [];
    var cleanupRankCheck = [];

    // cleanup
    mapObject(remainingResults, function (lb) {
      cleanupRankCheck.push(lb.rank);
      objectIterator(query(_this.settings.leaderboard.list, '.cl-lb-rank-' + lb.rank + '.cl-shared-rank'), function (obj) {
        remove(obj);
      });
    });

    objectIterator(query(_this.settings.leaderboard.container, '.cl-lb-row'), function (obj) {
      var rank = parseInt(obj.dataset.rank);
      if (cleanupRankCheck.indexOf(rank) === -1 && rank > _this.settings.leaderboard.defaultEmptyList) {
        remove(obj);
      }
    });

    mapObject(remainingResults, function (lb) {
      var count = 0;
      var icon = _this.settings.lbWidget.populateIdenticonBase64Image(lb.memberId);
      var memberFound = (_this.settings.lbWidget.settings.memberId === lb.memberId || _this.settings.lbWidget.settings.memberId === lb.memberRefId);
      var memberName = (memberFound) ? _this.settings.lbWidget.settings.translation.leaderboard.you : lb.name;
      var reward = _this.getReward(lb.rank);
      var change = (typeof lb.change === 'undefined') ? 0 : lb.change;
      var growthType = (change < 0) ? 'down' : (change > 0 ? 'up' : 'same');
      var growthIcon = "<span class='cl-growth-icon cl-growth-" + growthType + "'></span>";
      var formattedPoints = _this.settings.lbWidget.settings.leaderboard.pointsFormatter(lb.points);

      if (rankCheck.indexOf(lb.rank) !== -1) {
        for (var rc = 0; rc < rankCheck.length; rc++) {
          if (lb.rank === rankCheck[rc]) {
            count++;
          }
        }
      }

      _this.leaderboardRowUpdate(
        lb.rank,
        icon, // icon
        memberName,
        change,
        growthIcon, // growth
        formattedPoints,
        reward,
        count,
        memberFound,
        function (rank, icon, name, change, growth, points, reward, count, memberFound) {
          var newRow = _this.leaderboardRow(rank, icon, name, name, growth, points, reward, count, memberFound);
          var prevCellRow = query(_this.settings.leaderboard.container, '.cl-lb-rank-' + rank + '.cl-lb-count-' + (count - 1));

          if (prevCellRow !== null && typeof prevCellRow.length === 'undefined') {
            appendNext(prevCellRow, newRow);
          } else {
            _this.settings.leaderboard.list.appendChild(newRow);
          }
        }
      );

      rankCheck.push(lb.rank);
    });
  };

  this.updateLeaderboard = function () {
    var _this = this;
    var topResults = [];
    var remainingResults = [];

    _this.populateLeaderboardResultsWithDefaultEntries();

    mapObject(_this.settings.lbWidget.settings.leaderboard.leaderboardData, function (lb) {
      if (lb.rank <= _this.settings.leaderboard.topResultSize) {
        topResults.push(lb);
      } else {
        remainingResults.push(lb);
      }
    });

    _this.updateLeaderboardTopResults(topResults);
    _this.updateLeaderboardResults(remainingResults);

    var member = query(_this.settings.leaderboard.list, '.cl-lb-member-row');
    if (member !== null) {
      _this.missingMember(_this.isElementVisibleInView(member, _this.settings.leaderboard.list.parentNode));
      _this.missingMember(_this.isElementVisibleInView(member, _this.settings.leaderboard.resultContainer));
    } else {
      _this.missingMemberReset();
    }
  };

  this.updateLeaderboardTime = function () {
    var _this = this;
    var diff = moment(_this.settings.lbWidget.settings.competition.activeContest.scheduledStart).diff(moment());
    var date = _this.settings.lbWidget.settings.translation.miniLeaderboard.startsIn + ': ' + _this.settings.lbWidget.formatDateTime(moment.duration(diff));

    if (_this.settings.leaderboard.timerInterval) {
      clearTimeout(_this.settings.leaderboard.timerInterval);
    }

    if (diff <= 0 && _this.settings.lbWidget.settings.competition.activeContest.statusCode === 0) {
      date = _this.settings.lbWidget.settings.translation.miniLeaderboard.starting;
    } else if (_this.settings.lbWidget.settings.competition.activeContest.statusCode === 1) {
      date = _this.settings.lbWidget.settings.translation.tournaments.starting;
    } else if (_this.settings.lbWidget.settings.competition.activeContest.statusCode === 2) {
      diff = moment(_this.settings.lbWidget.settings.competition.activeContest.scheduledEnd).diff(moment());
      date = _this.settings.lbWidget.formatDateTime(moment.duration(diff));

      if (diff <= 0) {
        date = _this.settings.lbWidget.settings.translation.tournaments.finishing;
      }
    } else if (_this.settings.lbWidget.settings.competition.activeContest.statusCode === 3) {
      date = _this.settings.lbWidget.settings.translation.tournaments.finishing;
    } else if (_this.settings.lbWidget.settings.competition.activeContest.statusCode >= 4) {
      date = _this.settings.lbWidget.settings.translation.tournaments.finished;
    }

    _this.settings.headerDate.innerHTML = date;
    _this.settings.labelDate.innerHTML = date;
    _this.settings.detailsContainerDate.innerHTML = date;

    _this.settings.leaderboard.timerInterval = setTimeout(function () {
      _this.updateLeaderboardTime();
    }, 1000);
  };

  this.getActiveCompetitionDescription = function () {
    return (this.settings.lbWidget.settings.competition.activeContest !== null && this.settings.lbWidget.settings.competition.activeContest.description.length > 0) ? this.settings.lbWidget.settings.competition.activeContest.description : ((this.settings.lbWidget.settings.competition.activeCompetition !== null) ? this.settings.lbWidget.settings.competition.activeCompetition.description : '');
  };

  this.extractImage = function (body, imageContainer, isBodyVirtualOpt) {
    const _this = this;
    const activeImageContainer = closest(body, '.cl-main-section-image-banner-active');
    var imageFound = false;
    const isBodyVirtual = (typeof isBodyVirtualOpt === 'boolean') ? isBodyVirtualOpt : false;

    if (_this.settings.lbWidget.settings.competition.extractImageHeader) {
      objectIterator(query(body, 'img'), function (img, key, count) {
        if (count === 0) {
          imageFound = true;
          var newImg = img.cloneNode(true);
          addClass(newImg, 'cl-main-widget-lb-details-image');
          imageContainer.appendChild(newImg);

          remove(img);
        }
      });
    }

    if (!imageFound && activeImageContainer !== null) {
      removeClass(activeImageContainer, 'cl-main-section-image-banner-active');
    } else if (imageFound && activeImageContainer === null && _this.settings.lbWidget.settings.leaderboard.layoutSettings.imageBanner && !isBodyVirtual) {
      addClass(closest(body, '.cl-main-section-item'), 'cl-main-section-image-banner-active');
    }
  };

  this.leaderboardDetailsUpdate = function () {
    var _this = this;
    var mainLabel = query(_this.settings.section, '.cl-main-widget-lb-details-content-label-text');
    var body = null;

    if (!_this.settings.lbWidget.settings.leaderboard.layoutSettings.titleLinkToDetailsPage) {
      body = query(_this.settings.section, '.cl-main-widget-lb-details-description');
      body.innerHTML = _this.getActiveCompetitionDescription();
    }

    if (_this.settings.lbWidget.settings.leaderboard.layoutSettings.imageBanner) {
      var image = query(_this.settings.section, '.cl-main-widget-lb-details-image-container');
      image.innerHTML = '';

      if (body === null) {
        body = document.createElement('div');
        body.innerHTML = _this.getActiveCompetitionDescription();

        _this.extractImage(body, image, true);
      } else {
        _this.extractImage(body, image, false);
      }
    }

    mainLabel.innerHTML = (_this.settings.lbWidget.settings.competition.activeContest !== null) ? _this.settings.lbWidget.settings.competition.activeContest.label : _this.settings.lbWidget.settings.translation.tournaments.noAvailableCompetitions;
  };

  this.showEmbeddedCompetitionDetailsContent = function (callback) {
    if (hasClass(this.settings.section, 'cl-main-active-embedded-description')) {
      removeClass(this.settings.section, 'cl-main-active-embedded-description');
    } else {
      addClass(this.settings.section, 'cl-main-active-embedded-description');
    }
    if (typeof callback === 'function') callback();
  };

  this.hideEmbeddedCompetitionDetailsContent = function (callback) {
    removeClass(this.settings.section, 'cl-main-active-embedded-description');
    if (typeof callback === 'function') callback();
  };

  this.leaderboardOptInCheck = function () {
    var _this = this;
    var optIn = query(_this.settings.section, '.cl-main-widget-lb-optin-action');

    if (typeof _this.settings.lbWidget.settings.competition.activeCompetition !== 'undefined' && _this.settings.lbWidget.settings.competition.activeCompetition !== null && typeof _this.settings.lbWidget.settings.competition.activeCompetition.optinRequired === 'boolean' && _this.settings.lbWidget.settings.competition.activeCompetition.optinRequired) {
      if (typeof _this.settings.lbWidget.settings.competition.activeCompetition.optin === 'boolean' && !_this.settings.lbWidget.settings.competition.activeCompetition.optin) {
        optIn.innerHTML = _this.settings.lbWidget.settings.translation.tournaments.enter;
        optIn.parentNode.style.display = 'block';
      } else {
        optIn.parentNode.style.display = 'none';
      }
    } else {
      optIn.parentNode.style.display = 'none';
    }
  };

  // cleanup/recover activity
  this.preLoaderRerun = function () {
    var _this = this;

    if (_this.settings.preLoader.preLoaderActive && _this.settings.preLoader.preloaderCallbackRecovery !== null &&
      _this.settings.preLoader.preLoaderlastAttempt !== null && typeof _this.settings.preLoader.preLoaderlastAttempt === 'number' &&
      (_this.settings.preLoader.preLoaderlastAttempt + 8000) < new Date().getTime()) {
      _this.settings.preLoader.preloaderCallbackRecovery();
    }
  };

  this.preloader = function () {
    var _this = this;
    var preLoader = query(_this.settings.section, '.cl-main-widget-pre-loader');
    // var content = query(_this.settings.section, '.cl-main-widget-pre-loader-content');

    return {
      show: function (callback) {
        _this.settings.preLoader.preLoaderActive = true;
        _this.settings.preLoader.preLoaderlastAttempt = new Date().getTime();
        preLoader.style.display = 'block';
        setTimeout(function () {
          preLoader.style.opacity = 1;
        }, 20);

        if (_this.settings.preLoader.preloaderCallbackRecovery === null && typeof callback === 'function') {
          _this.settings.preLoader.preloaderCallbackRecovery = callback;
        }

        callback();
      },
      hide: function () {
        _this.settings.preLoader.preLoaderActive = false;
        _this.settings.preLoader.preLoaderlastAttempt = null;
        preLoader.style.opacity = 0;

        if (_this.settings.preLoader.preloaderCallbackRecovery !== null) {
          _this.settings.preLoader.preloaderCallbackRecovery = null;
        }

        setTimeout(function () {
          preLoader.style.display = 'none';
        }, 200);
      }
    };
  };

  this.destroyLayout = function () {
    var _this = this;

    if (_this.settings.container !== null) {
      remove(_this.settings.container);
      remove(_this.settings.overlayContainer);
    }

    _this.settings.container = null;
    _this.settings.overlayContainer = null;
  };

  this.loadLeaderboard = function (callback) {
    var _this = this;

    if (_this.settings.container === null) {
      _this.settings.container = _this.settings.lbWidget.settings.bindContainer.appendChild(_this.layout());
      _this.settings.overlayContainer = _this.settings.lbWidget.settings.bindContainer.appendChild(_this.overlayLayout());
      _this.settings.navigation = query(_this.settings.container, '.cl-main-widget-navigation-container');
      _this.settings.section = query(_this.settings.container, '.cl-main-widget-section-container');
      _this.settings.leaderboard.container = query(_this.settings.section, '.cl-main-widget-lb-leaderboard');
      _this.settings.leaderboard.header = query(_this.settings.leaderboard.container, '.cl-main-widget-lb-leaderboard-header-labels');
      _this.settings.leaderboard.resultContainer = query(_this.settings.leaderboard.container, '.cl-main-widget-lb-leaderboard-res-container');
      _this.settings.leaderboard.list = query(_this.settings.leaderboard.container, '.cl-main-widget-lb-leaderboard-body-res');
      _this.settings.leaderboard.topResults = query(_this.settings.leaderboard.container, '.cl-main-widget-lb-leaderboard-header-top-res');
      _this.settings.detailsContainer = query(_this.settings.container, '.cl-main-widget-lb-details-container');
      _this.settings.tournamentListContainer = query(_this.settings.container, '.cl-main-widget-tournaments-list');
      _this.settings.detailsContainerDate = query(_this.settings.container, '.cl-main-widget-lb-details-header-date');
      _this.settings.headerDate = query(_this.settings.container, '.cl-main-widget-lb-header-date');
      _this.settings.labelDate = query(_this.settings.container, '.cl-main-widget-lb-details-content-date');
      _this.settings.achievement.container = query(_this.settings.container, '.' + _this.settings.lbWidget.settings.navigation.achievements.containerClass);
      _this.settings.achievement.detailsContainer = query(_this.settings.container, '.cl-main-widget-ach-details-container');
      _this.settings.reward.container = query(_this.settings.container, '.' + _this.settings.lbWidget.settings.navigation.rewards.containerClass);
      _this.settings.reward.detailsContainer = query(_this.settings.container, '.cl-main-widget-reward-details-container');
      _this.settings.messages.container = query(_this.settings.container, '.' + _this.settings.lbWidget.settings.navigation.inbox.containerClass);
      _this.settings.messages.detailsContainer = query(_this.settings.container, '.cl-main-widget-inbox-details-container');

      _this.mainNavigationCheck();
      _this.leaderboardHeader();
    }

    _this.eventListeners();

    _this.leaderboardOptInCheck();
    _this.leaderboardDetailsUpdate();
    _this.updateLeaderboard();

    if (_this.settings.lbWidget.settings.competition.activeContest !== null) {
      _this.updateLeaderboardTime();
    }

    if (typeof callback === 'function') {
      callback();
    }
  };

  this.clearAll = function () {
    var _this = this;

    _this.settings.active = false;

    if (_this.settings.leaderboard.timerInterval) {
      clearTimeout(_this.settings.leaderboard.timerInterval);
    }

    _this.settings.preLoader.preLoaderActive = false;
  };

  this.hide = function (callback) {
    var _this = this;

    _this.clearAll();

    if (_this.settings.container !== null) {
      removeClass(_this.settings.container, 'cl-show');

      setTimeout(function () {
        _this.settings.container.style.display = 'none';
        _this.settings.overlayContainer.style.display = 'none';

        _this.hideCompetitionDetails();
        _this.hideAchievementDetails();

        if (typeof callback === 'function') {
          callback();
        }
      }, 30);
    } else if (typeof callback === 'function') {
      callback();
    }
  };

  this.missingMember = function (isVisible) {
    var _this = this;
    var area = query(_this.settings.container, '.cl-main-widget-lb-missing-member');
    var member = query(_this.settings.leaderboard.list, '.cl-lb-member-row');

    if (area !== null && member !== null) {
      area.innerHTML = member.innerHTML;
    }

    if (!isVisible) {
      if (area !== null && member !== null) {
        area.style.display = 'block';
      } else {
        area.style.display = 'none';
      }
    } else {
      area.style.display = 'none';
    }
  };

  this.missingMemberReset = function () {
    var _this = this;
    var area = query(_this.settings.container, '.cl-main-widget-lb-missing-member');
    area.innerHTML = '';
  };

  this.isElementVisibleInView = function (el, container) {
    var position = el.getBoundingClientRect();
    var elemContainer = container.getBoundingClientRect();
    var elemTop = position.top;
    var elemBottom = position.bottom;
    var elemHeight = position.height;

    return elemTop <= elemContainer.top
      ? elemContainer.top - elemTop <= elemHeight : elemBottom - elemContainer.bottom <= elemHeight;
  };

  var onresizeInitialised = false;
  this.eventListeners = function () {
    var _this = this;

    // unique solution to support horizontal mobile orientation
    if (_this.settings.leaderboard.resultContainer !== null && _this.settings.leaderboard.resultContainer.onscroll === null) {
      _this.settings.leaderboard.resultContainer.onscroll = function (evt) {
        evt.preventDefault();
        var member = query(_this.settings.leaderboard.list, '.cl-lb-member-row');

        if (member !== null) {
          _this.missingMember(_this.isElementVisibleInView(member, evt.target));
        }
      };
    }

    if (_this.settings.leaderboard.list !== null && _this.settings.leaderboard.list.parentNode.onscroll === null) {
      _this.settings.leaderboard.list.parentNode.onscroll = function (evt) {
        evt.preventDefault();
        var member = query(_this.settings.leaderboard.list, '.cl-lb-member-row');

        if (member !== null) {
          _this.missingMember(_this.isElementVisibleInView(member, evt.target));
        }
      };
    }

    if (!onresizeInitialised) {
      onresizeInitialised = true;
      window.onresize = function (evt) {
        var member = query(_this.settings.leaderboard.list, '.cl-lb-member-row');

        if (member !== null) {
          _this.missingMember(_this.isElementVisibleInView(member, _this.settings.leaderboard.list.parentNode));
          _this.missingMember(_this.isElementVisibleInView(member, _this.settings.leaderboard.resultContainer));
        }
      };
    }
  };

  // this.checkLeaderboardScrollContainer = function(){
  //  var _this = this,
  //    lbScrollContainer = query(_this.settings.leaderboard.container, ".cl-main-widget-lb-leaderboard-body");
  //
  //  if( scrollEnabled(lbScrollContainer) ){
  //    addClass(lbScrollContainer, "cl-element-scrollable");
  //  }else{
  //    removeClass(lbScrollContainer, "cl-element-scrollable");
  //  }
  // };

  this.competitionDetailsOptInButtonState = function () {
    var _this = this;
    var optIn = query(_this.settings.detailsContainer, '.cl-main-widget-lb-details-optin-action');

    if (typeof _this.settings.lbWidget.settings.competition.activeCompetition.optinRequired === 'boolean' && _this.settings.lbWidget.settings.competition.activeCompetition.optinRequired) {
      if (typeof _this.settings.lbWidget.settings.competition.activeCompetition.optin === 'boolean' && !_this.settings.lbWidget.settings.competition.activeCompetition.optin) {
        optIn.innerHTML = _this.settings.lbWidget.settings.translation.tournaments.enter;
        removeClass(optIn, 'cl-disabled');
      } else {
        optIn.innerHTML = _this.settings.lbWidget.settings.translation.tournaments.registered;
        addClass(optIn, 'cl-disabled');
      }
      optIn.parentNode.style.display = 'block';
    } else {
      optIn.parentNode.style.display = 'none';
    }
  };

  this.loadCompetitionDetails = function (callback) {
    var _this = this;
    var label = query(_this.settings.detailsContainer, '.cl-main-widget-lb-details-header-label');
    // var date = query(_this.settings.detailsContainer, '.cl-main-widget-lb-details-header-date');
    var body = query(_this.settings.detailsContainer, '.cl-main-widget-lb-details-body');
    var image = query(_this.settings.detailsContainer, '.cl-main-widget-lb-details-body-image-cont');

    image.innerHTML = '';
    label.innerHTML = (_this.settings.lbWidget.settings.competition.activeContest.label.length > 0) ? _this.settings.lbWidget.settings.competition.activeContest.label : _this.settings.lbWidget.settings.competition.activeCompetition.label;
    body.innerHTML = (_this.settings.lbWidget.settings.competition.activeContest.description.length > 0) ? _this.settings.lbWidget.settings.competition.activeContest.description : _this.settings.lbWidget.settings.competition.activeCompetition.description;
    _this.competitionDetailsOptInButtonState();

    _this.settings.detailsContainer.style.display = 'block';
    _this.settings.headerDate.style.display = 'none';

    _this.extractImage(body, image);

    setTimeout(function () {
      addClass(_this.settings.detailsContainer, 'cl-show');

      if (typeof callback === 'function') callback();
    }, 50);
  };

  this.loadCompetitionList = function (callback, ajaxInstance) {
    const _this = this;
    const listResContainer = query(_this.settings.tournamentListContainer, '.cl-main-widget-tournaments-list-body-res');
    const listIcon = query(_this.settings.container, '.cl-main-widget-lb-header-list-icon');
    const preLoader = _this.preloader();

    preLoader.show(function () {
      listIcon.style.opacity = '0';
      _this.settings.lbWidget.checkForAvailableCompetitions(function () {
        var accordionObj = _this.accordionStyle(_this.settings.tournamentsSection.accordionLayout, function (accordionSection, listContainer, topEntryContainer, layout) {
          var tournamentData = _this.settings.lbWidget.settings.tournaments[layout.type];

          if (typeof tournamentData !== 'undefined') {
            if (tournamentData.length === 0) {
              accordionSection.style.display = 'none';
            }
            mapObject(tournamentData, function (tournament, key, count) {
              if ((count + 1) <= layout.showTopResults && query(topEntryContainer, '.cl-tournament-' + tournament.id) === null) {
                var topEntryContaineRlistItem = _this.tournamentItem(tournament);
                topEntryContainer.appendChild(topEntryContaineRlistItem);
              }

              if (query(listContainer, '.cl-tournament-' + tournament.id) === null) {
                var listItem = _this.tournamentItem(tournament);
                listContainer.appendChild(listItem);
              }
            });
          }
        });

        listResContainer.innerHTML = '';
        listResContainer.appendChild(accordionObj);

        _this.settings.tournamentListContainer.style.display = 'block';
        setTimeout(function () {
          addClass(_this.settings.tournamentListContainer, 'cl-show');

          if (typeof callback === 'function') callback();

          preLoader.hide();
        }, 50);
      }, ajaxInstance);
    });
  };

  this.hideCompetitionList = function (callback) {
    var _this = this;
    const listIcon = query(_this.settings.container, '.cl-main-widget-lb-header-list-icon');

    listIcon.style.opacity = '1';
    _this.hideEmbeddedCompetitionDetailsContent();
    _this.missingMemberReset();

    removeClass(_this.settings.tournamentListContainer, 'cl-show');

    setTimeout(function () {
      _this.settings.tournamentListContainer.style.display = 'none';

      if (typeof callback === 'function') callback();
    }, 200);
  };

  this.hideCompetitionDetails = function (callback) {
    var _this = this;

    removeClass(_this.settings.detailsContainer, 'cl-show');
    setTimeout(function () {
      _this.settings.detailsContainer.style.display = 'none';
      _this.settings.headerDate.style.display = 'block';

      if (typeof callback === 'function') callback();
    }, 200);
  };

  this.achievementItem = function (ach, achieved, perc) {
    var _this = this;
    var listItem = document.createElement('div');
    var detailsContainer = document.createElement('div');
    var detailsWrapper = document.createElement('div');
    var label = document.createElement('div');
    var category = document.createElement('div');
    var description = document.createElement('div');
    var progressionWrapper = document.createElement('div');
    var progressionCont = document.createElement('div');
    var progressionBar = document.createElement('div');
    var moreButton = document.createElement('a');
    var cpomntainsImage = (typeof ach.icon !== 'undefined' && ach.icon.length > 0);

    listItem.setAttribute('class', 'cl-ach-list-item cl-ach-' + ach.id + (cpomntainsImage ? ' cl-ach-with-image' : ''));
    detailsContainer.setAttribute('class', 'cl-ach-list-details-cont');
    detailsWrapper.setAttribute('class', 'cl-ach-list-details-wrap');
    label.setAttribute('class', 'cl-ach-list-details-label');
    category.setAttribute('class', 'cl-ach-list-details-category');
    description.setAttribute('class', 'cl-ach-list-details-description');
    progressionWrapper.setAttribute('class', 'cl-ach-list-progression');
    progressionCont.setAttribute('class', 'cl-ach-list-progression-cont');
    progressionBar.setAttribute('class', 'cl-ach-list-progression-bar');
    moreButton.setAttribute('class', 'cl-ach-list-more');

    moreButton.dataset.id = ach.id;
    moreButton.innerHTML = _this.settings.lbWidget.settings.translation.achievements.more;
    moreButton.href = 'javascript:void(0);';

    listItem.dataset.id = ach.id;

    label.innerHTML = ach.name;
    category.innerHTML = ach.category.join(', ');

    detailsWrapper.appendChild(label);
    detailsWrapper.appendChild(category);
    detailsWrapper.appendChild(description);

    if (cpomntainsImage) {
      var image = new Image();
      var imageIconWrapper = document.createElement('div');
      imageIconWrapper.setAttribute('class', 'cl-ach-list-item-img-wrapper');
      image.setAttribute('class', 'cl-ach-list-item-img');

      image.src = _this.settings.lbWidget.settings.uri.gatewayDomain + _this.settings.lbWidget.settings.uri.assets.replace(':attachmentId', ach.icon);
      image.alt = ach.name;

      // image.onload = function(){
      // };

      imageIconWrapper.appendChild(image);
      detailsContainer.appendChild(imageIconWrapper);
    }

    detailsContainer.appendChild(detailsWrapper);

    progressionCont.appendChild(progressionBar);
    progressionWrapper.appendChild(progressionCont);
    progressionWrapper.appendChild(moreButton);

    listItem.appendChild(detailsContainer);
    listItem.appendChild(progressionWrapper);

    return listItem;
  };

  this.achievementListLayout = function (achievementData) {
    var _this = this;
    var achList = query(_this.settings.section, '.' + _this.settings.lbWidget.settings.navigation.achievements.containerClass + ' .cl-main-widget-ach-list-body-res');

    mapObject(achievementData, function (ach) {
      if (query(achList, '.cl-ach-' + ach.id) === null) {
        var listItem = _this.achievementItem(ach);

        achList.appendChild(listItem);
      }
    });
  };

  this.loadAchievementDetails = function (data, callback) {
    var _this = this;
    var label = query(_this.settings.achievement.detailsContainer, '.cl-main-widget-ach-details-header-label');
    var body = query(_this.settings.achievement.detailsContainer, '.cl-main-widget-ach-details-body');
    var image = query(_this.settings.achievement.detailsContainer, '.cl-main-widget-ach-details-body-image-cont');

    image.innerHTML = '';

    label.innerHTML = data.data.name;
    body.innerHTML = data.data.description;

    if (_this.settings.lbWidget.settings.achievements.extractImageHeader) {
      var imageLookup = query(body, 'img');
      objectIterator(imageLookup, function (img, key, count) {
        if (count === 0) {
          var newImg = img.cloneNode(true);
          image.appendChild(newImg);

          remove(img);
        }
      });
    }

    _this.settings.achievement.detailsContainer.style.display = 'block';
    setTimeout(function () {
      addClass(_this.settings.achievement.detailsContainer, 'cl-show');

      if (typeof callback === 'function') callback();
    }, 50);
  };

  this.hideAchievementDetails = function (callback) {
    var _this = this;

    removeClass(_this.settings.achievement.detailsContainer, 'cl-show');
    setTimeout(function () {
      _this.settings.achievement.detailsContainer.style.display = 'none';

      if (typeof callback === 'function') callback();
    }, 200);
  };

  this.loadRewardDetails = function (data, callback) {
    var _this = this;
    var label = query(_this.settings.reward.detailsContainer, '.cl-main-widget-reward-details-header-label');
    var body = query(_this.settings.reward.detailsContainer, '.cl-main-widget-reward-details-body');
    var image = query(_this.settings.reward.detailsContainer, '.cl-main-widget-reward-details-body-image-cont');
    var claimBtn = query(_this.settings.reward.detailsContainer, '.cl-main-widget-reward-claim-btn');
    var icon = query(_this.settings.reward.detailsContainer, '.cl-main-widget-reward-winnings-icon');
    var value = query(_this.settings.reward.detailsContainer, '.cl-main-widget-reward-winnings-value');

    label.innerHTML = data.data.reward.rewardName;
    body.innerHTML = data.data.reward.description;
    value.innerHTML = _this.settings.lbWidget.settings.partialFunctions.rewardFormatter(data.data.reward);
    claimBtn.dataset.id = data.data.id;

    if (data.data.claimed) {
      addClass(claimBtn, 'cl-claimed');
      claimBtn.innerHTML = _this.settings.lbWidget.settings.translation.rewards.claimed;
    } else {
      removeClass(claimBtn, 'cl-claimed');
      claimBtn.innerHTML = _this.settings.lbWidget.settings.translation.rewards.claim;
    }

    if (typeof data.data.reward.icon !== 'undefined') {
      icon.innerHTML = '';

      var _image = new Image();
      var imageIconWrapper = document.createElement('div');
      imageIconWrapper.setAttribute('class', 'cl-reward-list-item-img-wrapper');
      _image.setAttribute('class', 'cl-reward-list-item-img');

      _image.src = _this.settings.lbWidget.settings.uri.gatewayDomain + _this.settings.lbWidget.settings.uri.assets.replace(':attachmentId', data.data.reward.icon);
      _image.alt = _this.settings.lbWidget.settings.partialFunctions.rewardFormatter(data.data.reward);

      icon.appendChild(_image);
    } else {
      icon.innerHTML = "<span class='cl-place-holder-reward-image'></span>";
    }

    objectIterator(query(body, 'img'), function (img, key, count) {
      if (count === 0) {
        var newImg = img.cloneNode(true);
        image.innerHTML = '';
        image.appendChild(newImg);

        remove(img);
      }
    });

    _this.settings.reward.detailsContainer.style.display = 'block';
    setTimeout(function () {
      addClass(_this.settings.reward.detailsContainer, 'cl-show');

      if (typeof callback === 'function') callback();
    }, 50);
  };

  this.loadMessageDetails = function (data, callback) {
    var _this = this;
    var label = query(_this.settings.messages.detailsContainer, '.cl-main-widget-inbox-details-header-label');
    var body = query(_this.settings.messages.detailsContainer, '.cl-main-widget-inbox-details-body');

    label.innerHTML = data.data.subject;
    body.innerHTML = data.data.body;

    _this.settings.messages.detailsContainer.style.display = 'block';
    setTimeout(function () {
      addClass(_this.settings.messages.detailsContainer, 'cl-show');

      if (typeof callback === 'function') callback();
    }, 50);
  };

  this.hideRewardDetails = function (callback) {
    var _this = this;

    removeClass(_this.settings.reward.detailsContainer, 'cl-show');
    setTimeout(function () {
      _this.settings.reward.detailsContainer.style.display = 'none';

      if (typeof callback === 'function') callback();
    }, 200);
  };

  this.hideMessageDetails = function (callback) {
    var _this = this;

    removeClass(_this.settings.messages.detailsContainer, 'cl-show');
    setTimeout(function () {
      _this.settings.messages.detailsContainer.style.display = 'none';

      if (typeof callback === 'function') callback();
    }, 200);
  };

  this.updateAchievementProgressionAndIssued = function (issued, progression) {
    var _this = this;
    var achList = query(_this.settings.section, '.' + _this.settings.lbWidget.settings.navigation.achievements.containerClass + ' .cl-main-widget-ach-list-body-res');

    objectIterator(query(achList, '.cl-ach-list-item'), function (ach) {
      var id = ach.dataset.id;
      var issuedStatus = (issued.indexOf(id) !== -1);

      var perc = 0;
      mapObject(progression, function (pr) {
        if (pr.achievementId === id) {
          perc = (parseFloat(pr.goalPercentageComplete) * 100).toFixed(1);
        }
      });

      if (ach !== null) {
        var bar = query(ach, '.cl-ach-list-progression-bar');

        if (issuedStatus) {
          addClass(bar, 'cl-ach-complete');
          bar.innerHTML = _this.settings.lbWidget.settings.translation.achievements.complete;
          bar.style.width = '100%';
        } else {
          var percValue = ((perc > 1 || perc === 0) ? perc : 1) + '%';
          bar.innerHTML = (perc > 25 || (perc > 15 && parseInt(_this.settings.section.offsetWidth) > 450)) ? percValue : '';
          bar.style.width = percValue;
        }
      }
    });
  };

  this.loadAchievements = function (callback) {
    var _this = this;

    _this.settings.lbWidget.checkForAvailableAchievements(function (achievementData) {
      _this.settings.lbWidget.updateAchievementNavigationCounts();
      _this.achievementListLayout(achievementData);

      var idList = [];
      mapObject(_this.settings.lbWidget.settings.achievements.list, function (ach) {
        idList.push(ach.id);
      });

      setTimeout(function () {
        _this.settings.lbWidget.checkForMemberAchievementsIssued(function (issued) {
          _this.settings.lbWidget.checkForMemberAchievementsProgression(idList, function (progression) {
            _this.updateAchievementProgressionAndIssued(issued, progression);
          });
        });
      }, 400);

      if (typeof callback === 'function') {
        callback();
      }
    });
  };

  this.rewardItem = function (rew) {
    var _this = this;
    var listItem = document.createElement('div');
    var detailsContainer = document.createElement('div');
    var detailsWrapper = document.createElement('div');
    var label = document.createElement('div');
    var description = document.createElement('div');

    listItem.setAttribute('class', 'cl-rew-list-item cl-rew-' + rew.id);
    detailsContainer.setAttribute('class', 'cl-rew-list-details-cont');
    detailsWrapper.setAttribute('class', 'cl-rew-list-details-wrap');
    label.setAttribute('class', 'cl-rew-list-details-label');
    description.setAttribute('class', 'cl-rew-list-details-description');

    listItem.dataset.id = rew.id;
    var labelText = stripHtml(rew.subject);
    var descriptionText = stripHtml(rew.body);

    if (typeof rew.prize !== 'undefined') {
      listItem.dataset.rewardId = rew.prize.id;
      labelText = stripHtml(rew.subject + ' - ' + rew.prize.reward.rewardName + ' (' + _this.settings.lbWidget.settings.partialFunctions.rewardFormatter(rew.prize.reward) + ')');
      descriptionText = stripHtml((typeof rew.prize.reward.description !== 'undefined' && rew.prize.reward.description.length > 0) ? rew.prize.reward.description : rew.body);
    }

    label.innerHTML = (labelText.length > 80) ? (labelText.substr(0, 80) + '...') : labelText;
    description.innerHTML = (descriptionText.length > 200) ? (descriptionText.substr(0, 200) + '...') : descriptionText;

    detailsWrapper.appendChild(label);
    detailsWrapper.appendChild(description);
    detailsContainer.appendChild(detailsWrapper);
    listItem.appendChild(detailsContainer);

    return listItem;
  };

  this.messageItem = function (inbox) {
    // var _this = this;
    var listItem = document.createElement('div');
    var detailsContainer = document.createElement('div');
    var detailsWrapper = document.createElement('div');
    var label = document.createElement('div');
    var description = document.createElement('div');
    var content = stripHtml(inbox.body);

    listItem.setAttribute('class', 'cl-inbox-list-item cl-inbox-' + inbox.id);
    detailsContainer.setAttribute('class', 'cl-inbox-list-details-cont');
    detailsWrapper.setAttribute('class', 'cl-inbox-list-details-wrap');
    label.setAttribute('class', 'cl-inbox-list-details-label');
    description.setAttribute('class', 'cl-inbox-list-details-description');

    listItem.dataset.id = inbox.id;
    label.innerHTML = (inbox.subject.length > 36) ? inbox.subject.substr(0, 36) + '...' : inbox.subject;
    description.innerHTML = (content.length > 60) ? content.substr(0, 60) + '...' : content;

    detailsWrapper.appendChild(label);
    detailsWrapper.appendChild(description);
    detailsContainer.appendChild(detailsWrapper);
    listItem.appendChild(detailsContainer);

    return listItem;
  };

  this.tournamentItem = function (tournament) {
    // var _this = this;
    var listItem = document.createElement('div');
    var detailsContainer = document.createElement('div');
    var detailsWrapper = document.createElement('div');
    var label = document.createElement('div');
    var description = document.createElement('div');
    var descriptionContent = stripHtml(tournament.description);

    listItem.setAttribute('class', 'cl-tour-list-item cl-tour-' + tournament.id);
    detailsContainer.setAttribute('class', 'cl-tour-list-details-cont');
    detailsWrapper.setAttribute('class', 'cl-tour-list-details-wrap');
    label.setAttribute('class', 'cl-tour-list-details-label');
    description.setAttribute('class', 'cl-tour-list-details-description');

    listItem.dataset.id = tournament.id;
    label.innerHTML = tournament.label;
    description.innerHTML = (descriptionContent.length > 100) ? descriptionContent.substr(0, 100) + '...' : descriptionContent;

    detailsWrapper.appendChild(label);
    detailsWrapper.appendChild(description);
    detailsContainer.appendChild(detailsWrapper);
    listItem.appendChild(detailsContainer);

    return listItem;
  };

  this.rewardsListLayout = function (rewards, availableRewards, expiredRewards) {
    var _this = this;
    var rewardList = query(_this.settings.section, '.' + _this.settings.lbWidget.settings.navigation.rewards.containerClass + ' .cl-main-widget-reward-list-body-res');

    var accordionObj = _this.accordionStyle(_this.settings.rewardsSection.accordionLayout, function (accordionSection, listContainer, topEntryContainer, layout) {
      var rewardData = _this.settings.lbWidget.settings.rewards[layout.type];

      if (typeof rewardData !== 'undefined') {
        if (rewardData.length === 0) {
          accordionSection.style.display = 'none';
        }
        mapObject(rewardData, function (rew, key, count) {
          if ((count + 1) <= layout.showTopResults && query(topEntryContainer, '.cl-reward-' + rew.id) === null) {
            var topEntryContaineRlistItem = _this.rewardItem(rew);
            topEntryContainer.appendChild(topEntryContaineRlistItem);
          }

          if (query(listContainer, '.cl-reward-' + rew.id) === null) {
            var listItem = _this.rewardItem(rew);
            listContainer.appendChild(listItem);
          }
        });
      }
    });

    rewardList.innerHTML = '';
    rewardList.appendChild(accordionObj);

    // mapObject(rewardData, function(rew){
    //   if( query(rewardList, ".cl-reward-" + rew.id) === null ) {
    //     var listItem = _this.rewardItem(rew);
    //
    //     rewardList.appendChild(listItem);
    //   }
    // });
  };

  this.messagesListLayout = function (rewards, availableRewards, expiredRewards) {
    var _this = this;
    var messageList = query(_this.settings.section, '.' + _this.settings.lbWidget.settings.navigation.inbox.containerClass + ' .cl-main-widget-inbox-list-body-res');

    messageList.innerHTML = '';

    mapObject(_this.settings.lbWidget.settings.messages.messages, function (inboxItem, key, count) {
      var listItem = _this.messageItem(inboxItem);
      messageList.appendChild(listItem);
    });
  };

  this.loadRewards = function (callback) {
    var _this = this;

    _this.settings.lbWidget.checkForAvailableRewards(function (rewards, availableRewards, expiredRewards) {
      _this.settings.lbWidget.updateRewardsNavigationCounts();
      _this.rewardsListLayout(rewards, availableRewards, expiredRewards);

      if (typeof callback === 'function') {
        callback();
      }
    });
  };

  this.loadMessages = function (callback) {
    var _this = this;

    _this.settings.lbWidget.checkForAvailableMessages(function (rewards, availableRewards, expiredRewards) {
      _this.messagesListLayout(rewards, availableRewards, expiredRewards);

      if (typeof callback === 'function') {
        callback();
      }
    });
  };

  var changeInterval;
  var changeContainerInterval;
  this.navigationSwitch = function (target, callback) {
    var _this = this;
    var preLoader = _this.preloader();

    if (_this.settings.navigationSwitchInProgress && _this.settings.navigationSwitchLastAtempt + 3000 < new Date().getTime()) {
      _this.settings.navigationSwitchInProgress = false;
    }

    if (!_this.settings.navigationSwitchInProgress) {
      _this.settings.navigationSwitchInProgress = true;
      _this.settings.navigationSwitchLastAtempt = new Date().getTime();

      if (!hasClass(target.parentNode, 'cl-active-nav')) {
        preLoader.show(function () {
          if (changeInterval) clearTimeout(changeInterval);
          if (changeContainerInterval) clearTimeout(changeContainerInterval);

          objectIterator(query(_this.settings.container, '.cl-main-widget-navigation-items .cl-active-nav'), function (obj) {
            removeClass(obj, 'cl-active-nav');
          });

          objectIterator(query(_this.settings.container, '.cl-main-widget-section-container .cl-main-active-section'), function (obj) {
            removeClass(obj, 'cl-main-active-section');
            setTimeout(function () {
              obj.style.display = 'none';
            }, 150);
          });

          changeContainerInterval = setTimeout(function () {
            if (hasClass(target, 'cl-main-widget-navigation-lb-icon')) {
              _this.loadLeaderboard(function () {
                var lbContainer = query(_this.settings.container, '.cl-main-widget-section-container .' + _this.settings.lbWidget.settings.navigation.tournaments.containerClass);

                lbContainer.style.display = 'block';
                changeInterval = setTimeout(function () {
                  addClass(lbContainer, 'cl-main-active-section');
                }, 30);

                if (typeof callback === 'function') {
                  callback();
                }

                preLoader.hide();

                _this.settings.navigationSwitchInProgress = false;
              });
            } else if (hasClass(target, 'cl-main-widget-navigation-ach-icon')) {
              _this.loadAchievements(function () {
                var achContainer = query(_this.settings.container, '.cl-main-widget-section-container .' + _this.settings.lbWidget.settings.navigation.achievements.containerClass);

                _this.settings.achievement.detailsContainer.style.display = 'none';

                achContainer.style.display = 'block';
                changeInterval = setTimeout(function () {
                  addClass(achContainer, 'cl-main-active-section');

                  if (typeof callback === 'function') {
                    callback();
                  }
                }, 30);

                preLoader.hide();

                _this.settings.navigationSwitchInProgress = false;
              });
            } else if (hasClass(target, 'cl-main-widget-navigation-rewards-icon')) {
              _this.loadRewards(function () {
                var rewardsContainer = query(_this.settings.container, '.cl-main-widget-section-container .' + _this.settings.lbWidget.settings.navigation.rewards.containerClass);

                rewardsContainer.style.display = 'block';
                changeInterval = setTimeout(function () {
                  addClass(rewardsContainer, 'cl-main-active-section');
                }, 30);

                if (typeof callback === 'function') {
                  callback();
                }

                preLoader.hide();

                _this.settings.navigationSwitchInProgress = false;
              });
            } else if (hasClass(target, 'cl-main-widget-navigation-inbox-icon')) {
              _this.loadMessages(function () {
                var inboxContainer = query(_this.settings.container, '.cl-main-widget-section-container .' + _this.settings.lbWidget.settings.navigation.inbox.containerClass);

                inboxContainer.style.display = 'block';
                changeInterval = setTimeout(function () {
                  addClass(inboxContainer, 'cl-main-active-section');
                }, 30);

                preLoader.hide();

                _this.settings.navigationSwitchInProgress = false;
              });
            }
          }, 250);

          addClass(target.parentNode, 'cl-active-nav');
        });
      } else if (typeof callback === 'function') {
        _this.settings.navigationSwitchInProgress = false;
        callback();
      }
    }
  };

  this.resetNavigation = function (callback) {
    var _this = this;
    const listIcon = query(_this.settings.container, '.cl-main-widget-lb-header-list-icon');

    objectIterator(query(_this.settings.container, '.cl-main-widget-navigation-items .cl-active-nav'), function (obj) {
      removeClass(obj, 'cl-active-nav');
    });

    objectIterator(query(_this.settings.container, '.cl-main-widget-section-container .cl-main-active-section'), function (obj) {
      obj.style.display = 'none';
      removeClass(obj, 'cl-main-active-section');
    });

    var activeNave = false;
    objectIterator(query(_this.settings.container, '.cl-main-widget-navigation-container .cl-main-widget-navigation-item'), function (navItem, key, count) {
      if (!activeNave && !hasClass(navItem, 'cl-hidden-navigation-item')) {
        _this.navigationSwitch(query(navItem, '.cl-main-navigation-item'));
        activeNave = true;
      }
    });

    listIcon.style.opacity = '1';
    _this.hideEmbeddedCompetitionDetailsContent();
    _this.hideCompetitionList();

    setTimeout(function () {
      if (typeof callback !== 'undefined') callback();
    }, 70);
  };

  this.initLayout = function (callback) {
    var _this = this;

    _this.settings.active = true;

    _this.loadLeaderboard();

    _this.settings.container.style.display = 'block';
    _this.settings.overlayContainer.style.display = 'block';
    setTimeout(function () {
      addClass(_this.settings.container, 'cl-show');

      var member = query(_this.settings.leaderboard.list, '.cl-lb-member-row');
      if (member !== null) {
        _this.missingMember(_this.isElementVisibleInView(member, _this.settings.leaderboard.list.parentNode));
        _this.missingMember(_this.isElementVisibleInView(member, _this.settings.leaderboard.resultContainer));
      } else {
        _this.missingMemberReset();
      }

      _this.resetNavigation(callback);
    }, 30);
  };
};