sap.ui.define([
   'sap/ui/core/Component',
   'sap/ui/core/UIComponent',
   'sap/ui/core/mvc/Controller',
   "sap/ui/core/ResizeHandler",
   'rootui5/eve7/lib/EveManager',
   'rootui5/eve7/lib/EveScene'
], function (Component, UIComponent, Controller, ResizeHandler, EveManager, EveScene) {

   "use strict";

   return Controller.extend("rootui5.eve7.Controller.GL", {

      //==============================================================================
      // Initialization, bootstrap, destruction & cleanup.
      //==============================================================================

      onInit : function()
      {
         // let id = this.getView().getId();

         let viewData = this.getView().getViewData();
         if (viewData)
         {
            this.setupManagerAndViewType(viewData);
         }
         else
         {
            UIComponent.getRouterFor(this).getRoute("View").attachPatternMatched(this.onViewObjectMatched, this);
         }

         this._render_html  = false;
         this.htimeout = 250;

         ResizeHandler.register(this.getView(), this.onResize.bind(this));
      },

      onViewObjectMatched: function(oEvent)
      {
         let args = oEvent.getParameter("arguments");

         // console.log('ON MATCHED', args.viewName);
         // console.log('MORE DATA', EVE.$eve7tmp);
         // console.log('COMPONENT DATA', Component.getOwnerComponentFor(this.getView()).getComponentData());

         this.setupManagerAndViewType(Component.getOwnerComponentFor(this.getView()).getComponentData(),
            args.viewName, EVE.$eve7tmp);
         this.mgr.controllers[0].setToolbarExpandedAction(this);
         delete EVE.$eve7tmp;

         this.checkViewReady();
      },

      // Initialization that can be done immediately onInit or later through UI5 bootstrap callbacks.
      setupManagerAndViewType: function(data, viewName, moredata)
      {
         delete this.standalone;
         delete this.viewer_class;
         if (this.viewer) {
            this.viewer.cleanup();
            delete this.viewer;
         }

         if (viewName)
         {
            data.standalone = viewName;
         }

         // console.log("VIEW DATA", data);

         if (moredata && moredata.mgr)
         {
            this.mgr        = moredata.mgr;
            this.eveViewerId  = moredata.eveViewerId;
            this.standalone = viewName;
            this.checkViewReady();
         }
         else if (data.standalone && data.conn_handle)
         {
            this.mgr        = new EveManager();
            this.standalone = data.standalone;
            this.mgr.UseConnection(data.conn_handle);
         }
         else
         {
            this.mgr       = data.mgr;
            this.eveViewerId = data.eveViewerId;
         }

         this.mgr.RegisterController(this);
         this.mgr.RegisterGlController(this);
      },

      // Called when HTML parent/container rendering is complete.
      onAfterRendering: function()
      {
         this._render_html = true;

         // TODO: should be specified somehow in XML file
         this.getView().$().css("overflow", "hidden").css("width", "100%").css("height", "100%").parent().css("overflow", "hidden");

         this.checkViewReady();
      },

      onEveManagerInit: function()
      {
         // called when manager was updated, need only in standalone modes to detect own element id
         if (!this.standalone) return;

         let viewers = this.mgr.FindViewers();

         // first check number of views to create
         let found = null;
         for (let n = 0; n < viewers.length; ++n)
         {
            if (viewers[n].fName.indexOf(this.standalone) == 0)
            {
               found = viewers[n];
               break;
            }
         }
         if (!found) return;

         this.eveViewerId = found.fElementId;

         this.checkViewReady();
      },

      /*
      // Function called from GuiPanelController.
      onExit: function()
      {
         // QQQQ EveManager does not have Unregister ... nor UnregisterController
         if (this.mgr) this.mgr.Unregister(this);
         // QQQQ plus, we should unregister this as gl-controller, too
      },*/

      // Checks if all initialization is performed and startup renderer.
      checkViewReady: function()
      {
         if (!this.mgr || !this._render_html || !this.eveViewerId || this.viewer_class) return;

         this.viewer_class = this.mgr.handle.getUserArgs("GLViewer");
         if ((this.viewer_class != "JSRoot") && (this.viewer_class != "Three") && (this.viewer_class != "RCore"))
            this.viewer_class = "Three";

         this.htimeout = this.mgr.handle.getUserArgs("HTimeout");
         if (this.htimeout === undefined) this.htimeout = 250;

         // when "Reset" - reset camera position
         this.dblclick_action = this.mgr.handle.getUserArgs("DblClick");

         sap.ui.require(['rootui5/eve7/lib/GlViewer' + this.viewer_class],
               function(GlViewer) {
                  this.viewer = new GlViewer(this.viewer_class);
                  this.viewer.init(this);
               }.bind(this));
      },

      // Callback from GlViewer class after initialization is complete
      glViewerInitDone: function()
      {
         ResizeHandler.register(this.getView(), this.onResize.bind(this));
      },

      //==============================================================================
      // Common functions between THREE and GeoPainter
      //==============================================================================

      /** returns container for 3d objects */
      getSceneContainer: function(scene)
      {
         let parent = scene.IsOverlay ? this.viewer.get_overlay_scene() : this.viewer.get_top_scene();
         let scene_name = "scene" + scene.id;

         for (let k = 0; k < parent.children.length; ++k)
         {
            if (parent.children[k]._eve_name === scene_name)
            {
               return parent.children[k];
            }
         }

         let obj3d = this.viewer.make_object();
         obj3d._eve_name = scene_name;
         parent.add(obj3d);
         return obj3d;
      },

      createScenes: function()
      {
         if (this.created_scenes !== undefined) return;
         this.created_scenes = [];

         // only when rendering completed - register for modify events
         let element = this.mgr.GetElement(this.eveViewerId);

         let tlabel = this.getView().byId("titleLabel");
         tlabel.setText(element.fName);
         // loop over scene and add dependency
         for (let scene of element.childs)
         {
            this.created_scenes.push(new EveScene(this.mgr, scene, this));
         }
      },

      redrawScenes: function()
      {
         if (!this.created_scenes) return;

         for (let s of this.created_scenes)
            s.redrawScene();
      },

      removeScenes: function() {
         if (!this.created_scenes) return;

         for (let s of this.created_scenes)
            s.removeScene();
         delete this.created_scenes;
      },

      /// invoked from ResizeHandler
      onResize: function(event)
      {
         // TODO: should be specified somehow in XML file
         if (this.viewer_class != "RCore") {
            this.getView().$().css("overflow", "hidden").css("width", "100%").css("height", "100%");
         }

         if (this.resize_tmout) clearTimeout(this.resize_tmout);

         // MT 2020/09/09: On Chrome, delay up to 200ms gets executed immediately.
         this.resize_tmout = setTimeout(this.onResizeTimeout.bind(this), 250);
      },

      onResizeTimeout: function()
      {
         delete this.resize_tmout;
         if (this.viewer) this.viewer.onResizeTimeout();
      },

      /** Called from JSROOT context menu when object selected for browsing */
      invokeBrowseOf: function(obj_id) {
         this.mgr.SendMIR("BrowseElement(" + obj_id + ")", 0, "ROOT::Experimental::REveManager");
      },

      getEveCameraType : function(){
          let vo = this.mgr.GetElement(this.eveViewerId);
          return vo.CameraType;
      },

      isEveCameraPerspective: function() {
         let vo = this.mgr.GetElement(this.eveViewerId);
         return vo.camera.type.startsWith("Persp");
      },

      switchSingle: function()
      {
         let oRouter = UIComponent.getRouterFor(this);
         EVE.$eve7tmp = { mgr: this.mgr, eveViewerId: this.eveViewerId};
         oRouter.navTo("View", { viewName: this.mgr.GetElement(this.eveViewerId).fName });
      },

      swap: function ()
      {
         this.mgr.controllers[0].switchViewSides(this.mgr.GetElement(this.eveViewerId));
      },

      detachViewer: function()
      {
         this.mgr.controllers[0].removeView(this.mgr.GetElement(this.eveViewerId));
         this.destroy();
      },

      updateViewerAttributes : function()
      {
         if (this.viewer) {
            this.viewer.updateViewerAttributes();
         }
      }

   });

});
