text: ///////////////////////////////////////////////////////////////////////////
  // Copyright © Esri. All Rights Reserved.
  //
  // Licensed under the Apache License Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //    http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  ///////////////////////////////////////////////////////////////////////////
  
  define(['dojo/_base/declare',
      'dojo/_base/lang',
      'dojo/_base/html',
      'dojo/_base/array',
      'dojo/on',
      'dojo/keys',
      'dojo/aspect',
      'dojo/topic',
      'jimu/BaseWidgetPanel',
      'jimu/BaseWidgetFrame',
      'jimu/utils',
      'dojo/query',
      'dojo/dom-class',
      './FoldableDijit',
      './FoldableWidgetFrame',
      'dijit/registry'
    ],
    function (
      declare, lang, html, array, on, keys, aspect, topic, BaseWidgetPanel,
      BaseWidgetFrame, utils, query, domClass, FoldableDijit, FoldableWidgetFrame, registry
    ) {
      var borderRadius = '0px';
  
      /* global jimuConfig */
  
      return declare([BaseWidgetPanel, FoldableDijit], {
        baseClass: 'jimu-panel jimu-foldable-dijit jimu-foldable-panel',
  
        closeTolerance: 30,
  
        openAnimation: 'fadeIn',
        closeAnimation: 'fadeOut',
        animationDuration: 500,
  
        postMixInProperties: function () {
          this.headerNls = window.jimuNls.panelHeader;
        },
        startup: function () {
          this.titleHeight = 35;
          this.inherited(arguments);
          this._switchParentNode();
          html.addClass(this.titleNode, 'jimu-panel-title');
          this.createFoldableBtn();
          this.createMaxBtn();
          this.createCloseBtn();
          this.panelManager.normalizePanel(this);
          //Set role attribute to widget dom node
          html.setAttr(this.domNode, 'role', 'application');
          this.own(on(this.domNode, 'keydown', lang.hitch(this, function (evt) {
            if (!html.hasClass(evt.target, 'close-btn') && evt.keyCode === keys.ESCAPE) {
              this.closeNode.focus();
            }
          })));
        },
  
        getPanelPosition: function () {
          var panelPosition;
          if (window.appInfo.isRunInMobile) {
            if (this.panelManager.getPositionOnMobile(this).top === 0) {
              panelPosition = this.panelManager.getPositionOnMobile(this);
              panelPosition.top = '39px';
            } else {
              panelPosition = this.panelManager.getPositionOnMobile(this);
            }
            return panelPosition;
          } else {
            var pos = lang.clone(this.position);
            if (typeof pos.width === 'undefined') {
              pos.width = 360;
            }
            if (this.windowState === 'minimized') {
              pos.bottom = 'auto';
              pos.height = this.titleHeight;
              pos.borderRadiusStyle = {
                borderTopLeftRadius: borderRadius,
                borderTopRightRadius: borderRadius,
                borderBottomLeftRadius: 0,
                borderBottomRightRadius: 0
              };
            } else {
              pos.bottom = this.position.bottom;
              pos.height = 'auto';
              pos.borderRadiusStyle = {
                borderTopLeftRadius: borderRadius,
                borderTopRightRadius: borderRadius,
                borderBottomLeftRadius: borderRadius,
                borderBottomRightRadius: borderRadius
              };
            }
  
            return pos;
          }
        },
  
        onNormalize: function () {
          this.resize();
          if (domClass.contains(this.foldableNode, "folded")) {
            domClass.remove(this.foldableNode, "folded");
          }
        },
  
        onMaximize: function () {
          this.resize();
          if (domClass.contains(this.foldableNode, "folded")) {
            domClass.remove(this.foldableNode, "folded");
          }
        },
  
        onMinimize: function () {
          this.resize();
          if (!domClass.contains(this.foldableNode, "folded")) {
            domClass.add(this.foldableNode, "folded");
          }
        },
  
        resize: function () {
          this._switchMaxBtn();
  
          var pos = this.getPanelPosition();
          //Changes For showing panel below header in mobile devices
          // if Panel is maximize or normalized then place panel just below the title
          if (this.windowState === 'maximized' && window.appInfo.isRunInMobile) {
            pos.top = '39px';
          }
  
          // Adjust map canvas area on opening and closing of panels and window resizing
          this._setMapCanvasArea(pos.top);
  
          //Changes For showing panel below header in mobile devices  */
          if (!window.appInfo.isRunInMobile) {
            pos.top = '39px';
            pos.right = '0';
            pos.bottom = '0';
          }
          if (this.position.zIndex) {
            pos.zIndex = this.position.zIndex;
          }
          var style = utils.getPositionStyle(pos);
  
          if (window.appInfo.isRunInMobile) {
            // apply following styles if app is running in small screen device
            // (mobile and tablet devices)
            if (window.innerWidth <= 760 || window.innerHeight <= 600) {
              //styles for mobile if panel is maximized then resize the panel width to 100%
              //else keep it to the width of 360px;
              if (this.windowState === 'maximized') {
                style.width = "100%";
              } else {
                // if window width is less than 760px then resize
                //  the panel width to 100% else keep it to the width of 360px;
                if (window.innerWidth <= 760) {
                  style.width = "100%";
                } else {
                  style.width = "360px";
                }
              }
              if (window.isRTL) {
                style.left = "0px";
              } else {
                style.left = "auto";
              }
              style.right = style.left === "0px" ? "auto" : style.right;
  
            } else {
              //styles for tablet
              style.width = "360px";
  
              if (window.isRTL) {
                style.left = "0px";
              } else {
                style.left = "auto";
              }
              style.right = style.left === "0px" ? "auto" : style.right;
            }
          } else {
            //styles for desktop browsers
            style.width = "360px";
  
            if (window.isRTL) {
              style.left = "0px";
            } else {
              style.left = "auto";
            }
            style.right = style.left === "0px" ? "auto" : style.right;
          }
  
          lang.mixin(style, pos.borderRadiusStyle);
          style.margin = 'none';
          style.marginLeft = '0';
          style.marginRight = '0';
          style.marginBottom = '0';
          style.marginTop = '0';
          html.setStyle(this.domNode, style);
  
          if (this.getChildren().length > 1) {
            this._setFrameSize(pos.contentHeight);
          }
  
          this.inherited(arguments);
        },
  
        reloadWidget: function (widgetConfig) {
          this.inherited(arguments);
          if (!this.isWidgetInPanel(widgetConfig)) {
            return;
          }
          if (!Array.isArray(this.config.widgets)) {
            this.setTitleLabel(widgetConfig.label);
          }
        },
  
        /*
        * set the position of widget panel
        * @String top: position in pixels from top
        * @memberOf themes/PlateauTheme/FoldablePanel/panel.js
        */
        _setMapCanvasArea: function (postionTop) {
          // if application is running in mobile device then adjust map bottom positioning
          // else for desktop devices adjust map right positioning right
          if (window.appInfo.isRunInMobile) {
            var attributeTableHeight = 0;
            if (query(".jimu-widget-attributetable")[0]) {
              attributeTableHeight = query(".jimu-widget-attributetable")[0].clientHeight;
            }
            // if panel state is minimized then keep map bottom position to 35px
            // else if it is maximized then resize bottom position to zero
            // else change it by top position to the panel
            if (this.windowState === 'minimized') {
              // if attribute table widget height is greater than 35px
              // then set bottom position to attributeTableHeight
              // else keep bottom position to 35px
              if ((attributeTableHeight > 0) && attributeTableHeight > 35) {
                topic.publish('changeMapPosition', {
                  bottom: attributeTableHeight
                });
              } else {
                // if it is touch devices or browser width is less than 760px
                // then set bottom position to 35px else set it to zero
                if (window.hasOwnProperty("ontouchstart") ||
                  window.ontouchstart !== undefined || window.innerWidth <= 760) {
                  topic.publish('changeMapPosition', {
                    bottom: '35px'
                  });
                } else {
                  topic.publish('changeMapPosition', {
                    bottom: '0px'
                  });
                }
              }
            } else if (this.windowState === 'maximized') {
              topic.publish('changeMapPosition', {
                bottom: "0px"
              });
            } else {
              // if attribute table widget height is greater than postionTop
              // then set bottom equal attributeTableHeight
              // else keep bottom as postionTop
              if ((attributeTableHeight > 0) && attributeTableHeight > postionTop) {
                topic.publish('changeMapPosition', {
                  bottom: attributeTableHeight
                });
              } else {
                // if it is touch devices or browser width is less than 760px
                // then set bottom position dynamically else set it to zero
                if (window.hasOwnProperty("ontouchstart") ||
                  window.ontouchstart !== undefined || window.innerWidth <= 760) {
                  topic.publish('changeMapPosition', {
                    bottom: postionTop
                  });
                } else {
                  topic.publish('changeMapPosition', {
                    bottom: '0px'
                  });
                }
              }
            }
          } else if (!window.appInfo.isRunInMobile) {
            // if browser state is minimized the adjust map right position to the zero
            // change it to 360px from right
            if (this.windowState === 'minimized') {
              topic.publish('changeMapPosition', {
                right: '0px'
              });
            } else {
              topic.publish('changeMapPosition', {
                right: '360px'
              });
  
              this._resizeAttributeTableinRTL();
            }
          }
        },
  
        /*
        * resizes the attribute table widget in case of RTL layout
        * after opening or closing, panel or other widgets
        * @memberOf widgets/HeaderController/widget.js
        */
        _resizeAttributeTableinRTL: function () {
          // if attribute table widget is available in the dom
          if (query(".jimu-widget-attributetable")[0]) {
            if (window.isRTL) {
              html.setStyle(query(".jimu-widget-attributetable")[0], 'right', '0px');
            } else {
              html.setStyle(query(".jimu-widget-attributetable")[0], 'left', '0px');
            }
            // if tab Container is  of attribute table widget is created in the dom
            if (query(".dijitTabContainer", query(".jimu-widget-attributetable")[0])[0]) {
              registry.byId(query(".dijitTabContainer",
                query(".jimu-widget-attributetable")[0])[0].id).resize();
            }
          }
        },
  
        updateConfig: function (_config) {
          this.inherited(arguments);
          this.setTitleLabel(_config.label);
        },
  
        _switchMaxBtn: function () {
          // if window width is less than 760px or window innerHeight is less than
          // 600px then show the maximize button else hide the maximize button
          if (window.appInfo.isRunInMobile && (window.innerWidth <= 760 ||
            window.innerHeight <= 600)) {
            html.setStyle(this.maxNode, 'display', '');
          } else {
            html.setStyle(this.maxNode, 'display', 'none');
          }
        },
  
        _switchParentNode: function () {
          html.place(this.domNode, jimuConfig.layoutId);
        },
  
        _setFrameSize: function (contentHeight) {
          var h, openedPaneCount = 0;
  
          //openedPaneCount should >= 1
          array.forEach(this.getChildren(), function (frame) {
            if (!frame.folded) {
              openedPaneCount++;
            }
          }, this);
  
          if (typeof contentHeight === 'undefined') {
            contentHeight = html.getContentBox(this.containerNode).h;
          }
  
          h = (contentHeight - (this.getChildren().length - openedPaneCount) *
            this.getChildren()[0].titleHeight) / openedPaneCount;
          array.forEach(this.getChildren(), function (frame) {
            if (frame.folded) {
              html.setStyle(frame.domNode, {
                height: frame.titleHeight + 'px'
              });
            } else {
              html.setStyle(frame.domNode, {
                height: h + 'px'
              });
            }
            frame.resize();
          }, this);
        },
  
        createCloseBtn: function () {
          this.closeNode = html.create('div', {
            'class': 'close-btn jimu-float-trailing',
            'role': 'button',
            'tabindex': '0',
            'aria-label': this.headerNls.closeWindow
          }, this.btnsContainer);
  
          this.own(on(this.closeNode, 'click', lang.hitch(this, function (evt) {
            evt.stopPropagation();
            /* New Changes For showing panel below header in mobile devices  */
            query('.widget-open-symbol').addClass('esriCTHidden');
            /* New Changes For showing panel below header in mobile devices  */
            this.panelManager.closePanel(this);
          })));
  
          this.own(on(this.closeNode, 'keydown', lang.hitch(this, function (evt) {
            if (evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE) {
              this.panelManager.closePanel(this);
            }
            //not prevent user uses tab-key to widget's first focusable node, excluding groupPanel
            else if(!evt.shiftKey && evt.keyCode === keys.TAB){
              if(this.isGroupPanel){
                evt.preventDefault();
                this.firstTitleNode.focus();
              }
            }
          })));
        },
  
        createMaxBtn: function () {
          this.maxNode = html.create('div', {
            'class': 'max-btn jimu-float-trailing',
            'role': 'button',
            'aria-label': this.headerNls.maxWindow,
            'tabindex': 0
          }, this.btnsContainer);
  
          this.own(on(this.maxNode, 'click', lang.hitch(this, function (evt) {
            evt.stopPropagation();
            html.removeClass(this.titleNode, 'esriCTBorderBottom');
            this.onMaxNodeClick();
          })));
  
          //Add keydown event on max node
          //If ENTER key is press, proceed with node click event
          //IF ESC key is press, set focus to widget icon in the application header
          this.own(on(this.maxNode, 'keydown', lang.hitch(this, function (evt) {
            if (evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE) {
              evt.stopPropagation();
              this.onMaxNodeClick();
            }
            if (evt.keyCode === keys.ESCAPE) {
              evt.stopPropagation();
              var node = query(".jimu-state-selected")[0];
              if (node) {
                node.focus();
              }
            }
          })));
        },
  
        createFrame: function (widgetConfig) {
          var frame;
          if (this.config.widgets && this.config.widgets.length === 1 || !this.config.widgets) {
            frame = new BaseWidgetFrame();
          } else {
            frame = new FoldableWidgetFrame({
              label: widgetConfig.label,
              widgetManager: this.widgetManager
            });
  
            aspect.after(frame, 'onFoldStateChanged', lang.hitch(this, function () {
              var openedPaneCount = 0;
  
              this._setFrameSize();
              array.forEach(this.getChildren(), function (frame) {
                if (!frame.folded) {
                  openedPaneCount++;
                }
              }, this);
  
              array.forEach(this.getChildren(), function (frame) {
                if (!frame.folded && openedPaneCount === 1) {
                  frame.foldEnable = false;
                } else {
                  frame.foldEnable = true;
                }
              }, this);
            }));
          }
  
          return frame;
        },
  
        onFoldableNodeClick: function () {
          this.inherited(arguments);
  
          if (this.windowState === 'minimized') {
            html.removeClass(this.titleNode, 'esriCTBorderBottom');
            this.panelManager.normalizePanel(this);
          } else {
            this.panelManager.minimizePanel(this);
          }
          //set max btn's label
          html.setAttr(this.maxNode, 'aria-label', this.headerNls.maxWindow);
        },
  
        onMaxNodeClick: function () {
          html.removeClass(this.titleNode, 'esriCTBorderBottom');
          if (this.windowState === 'maximized') {
            html.setAttr(this.maxNode, 'aria-label', this.headerNls.maxWindow);
            this.panelManager.normalizePanel(this);
          } else {
            html.setAttr(this.maxNode, 'aria-label', this.headerNls.restoreWindow);
            this.panelManager.maximizePanel(this);
            //set foldable btn's styles
            this.folded = false;
            html.removeClass(this.foldableNode, 'folded');
            html.setAttr(this.foldableNode, 'aria-label', this.headerNls.foldWindow);
          }
        },
  
        moveTitle: function () {
          if (this.isFull) {
            if (this.folded) {
              html.setStyle(this.domNode, {
                top: (html.getMarginBox(jimuConfig.layoutId).h - this.titleHeight) + 'px'
              });
            } else {
              html.setStyle(this.domNode, {
                top: '0px'
              });
            }
          } else {
            html.setStyle(this.domNode, {
              top: this.position.top + 'px'
            });
          }
        }
      });
    });