<?xml version="1.0" encoding="utf-8"?>
<s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                      xmlns:s="library://ns.adobe.com/flex/spark" 
                      xmlns:mx="library://ns.adobe.com/flex/mx"
                      implements="mx.managers.IFocusManagerComponent"
                      width="100%"
                      height="100%"
                      addedToStage="onAddedToStage(event)"
                      show="onShow(event)"
                      hide="onHide(event)"
                      keyDown="onKeyDown(event)">
  <fx:Metadata>
    /**
     * General purpose viewer for resources, takes care of
     * retrieving the specific implementation based on the
     * resource to view.
     * 
     * @author Mathias Brodala
     */
  </fx:Metadata>

  <fx:Script>
    <![CDATA[
      import de.dtele.control.MediaManager;
      import de.dtele.data.IResource;
      import de.dtele.data.KeyCode;
      import de.dtele.data.MimeType;
      import de.dtele.data.MimeTypes;
      import de.dtele.providers.ProviderManager;
      import de.dtele.ui.components.viewer.IResourceViewer;
      
      import mx.collections.IList;
      import mx.events.FlexEvent;
      
      [Bindable("dataProviderChanged")]
      /**
       * The data provider
       */
      public var dataProvider:IList;

      [Bindable("selectedResourceChanged")]
      /**
       * The resource to view
       */
      public var selectedResource:IResource;
      
      /**
       * Stores information about the state before switching to fullscreen
       * 
       * Inspired by spark.components.VideoPlayer
       */
      protected var beforeFullScreenInfo:Object = {};

      /**
       * Retrieves the specific viewer for a resource
       */
      protected function onShow(e:FlexEvent):void {
        
        // Try to get a specific resource viewer
        var viewerClass:Class = ProviderManager.instance.getProvider(
          "resourceViewer", this.selectedResource.properties.type) as Class;
        var viewer:IResourceViewer;
        
        try {
          
          viewer = new viewerClass() as IResourceViewer;
        } catch (e:TypeError) {
          
          // Now try a more generic resource viewer common
          // to all resources of a media type (e.g. "image")
          var mimeType:MimeType = MimeTypes.split(this.selectedResource.properties.type);
          
          viewerClass = ProviderManager.instance.getProvider(
            "resourceViewer", mimeType.mediaType) as Class;
          viewer = new viewerClass() as IResourceViewer;
          
          // TODO: Fallback to a completely generic viewer
        }
        
        viewer.visible = false;
        viewer.addEventListener(Event.COMPLETE, this.onViewerComplete);
        
        viewer.view(this.selectedResource);
      }
      
      /**
       * Removes all resource viewers
       */
      protected function onHide(e:FlexEvent):void {
        
        this.container.removeAllElements();
      }
      
      /**
       * 
       */
      protected function onViewerComplete(e:Event):void {
        
        var viewer:IResourceViewer = e.target as IResourceViewer;

        this.container.removeAllElements();
        this.container.addElement(viewer);
        
        this.width = viewer.width;
        this.height = viewer.height;

        //viewer.width = this.width;
        //viewer.height = this.height;
        
        (e.target as IResourceViewer).visible = true;
      }
      
      /**
       * Triggers actions based on user input like switching to other
       * resources, toggling fullscreen and closing the viewer
       */
      protected function onKeyDown(e:KeyboardEvent):void {
        
        e.preventDefault();

        switch (e.keyCode) {
          
          case Keyboard.LEFT:
          case KeyCode.P:
            
            var previousIndex:int = this.dataProvider.getItemIndex(this.selectedResource) - 1;
            
            if (previousIndex < 0) {
              
              previousIndex = this.dataProvider.length - 1;
            }
            
            MediaManager.instance.selectedResource = this.dataProvider.getItemAt(previousIndex) as IResource;
            break;
          
          case Keyboard.RIGHT:
          case KeyCode.N:
            
            var nextIndex:int = this.dataProvider.getItemIndex(this.selectedResource) + 1;
            
            if (nextIndex >= this.dataProvider.length) {
              
              nextIndex = 0;
            }
            
            MediaManager.instance.selectedResource = this.dataProvider.getItemAt(nextIndex) as IResource;
            break;
          
          case KeyCode.F:
            
            this.stage.displayState = (
              this.stage.displayState == StageDisplayState.NORMAL
              ? StageDisplayState.FULL_SCREEN
              : StageDisplayState.NORMAL
            );
            break;
          
          case Keyboard.ESCAPE:
          case KeyCode.Q:
          case KeyCode.X:
            
            MediaManager.instance.selectedResource = null;
            break;
        }
      }
      
      /**
       * Sets up a listener to watch for fullscreen state changes of the stage
       */
      protected function onAddedToStage(event:Event):void {
        
        this.stage.addEventListener(FullScreenEvent.FULL_SCREEN, this.onFullScreen);
      }
      
      /**
       * Changes the appearance of the viewer in regular and fullscreen view
       * 
       * @see spark.components.VideoPlayer#fullScreenButton_clickHandler
       */
      protected function onFullScreen(e:FullScreenEvent):void {
        
        if (e.fullScreen) {
          
          // Store state properties for restore upon leaving fullscreen mode
          this.beforeFullScreenInfo = {
            x: this.container.x,
            y: this.container.y,
            explicitWidth: this.container.explicitWidth,
            explicitHeight: this.container.explicitHeight,
            percentWidth: this.container.percentWidth,
            percentHeight: this.container.percentHeight
          };
          
          // Resize to stage fullscreen size
          this.container.setLayoutBoundsSize(this.stage.fullScreenWidth, this.stage.fullScreenHeight, true);
          
          // Ensure dimensions are kept on layout changes
          // This can happen e.g. after the fullscreen info text ("Press Esc ...") was hidden
          this.container.explicitWidth = this.container.width;
          this.container.explicitHeight = this.container.height;
          
          // Move to 0,0
          this.container.setLayoutBoundsPosition(0, 0, true);
          
          // Force recalculation of properties and layout
          //this.validateNow();
          
        } else {
          
          // Restore state properties from before entering fullscreen mode
          this.container.x = this.beforeFullScreenInfo.x;
          this.container.y = this.beforeFullScreenInfo.y;
          this.container.explicitWidth = this.beforeFullScreenInfo.explicitWidth;
          this.container.explicitHeight = this.beforeFullScreenInfo.explicitHeight;
          this.container.percentWidth = this.beforeFullScreenInfo.percentWidth;
          this.container.percentHeight = this.beforeFullScreenInfo.percentHeight;

          // Force recalculation of size and display
          //this.invalidateSize();
          //this.invalidateDisplayList();
          //this.validateNow();
        }
      }

    ]]>
  </fx:Script>
  
  <s:BorderContainer
    id="container"
    horizontalCenter="0"
    verticalCenter="0"
    minWidth="0"
    minHeight="0"
    dropShadowVisible="true">
    
  </s:BorderContainer>
  
</s:SkinnableContainer>