/** @jsx React.DOM */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* jshint newcap:false */
/* global loop:true, React */

(function() {
  "use strict";

  // Stop the default init functions running to avoid conflicts.
  document.removeEventListener('DOMContentLoaded', loop.panel.init);
  document.removeEventListener('DOMContentLoaded', loop.conversation.init);

  // 1. Desktop components
  // 1.1 Panel
  var PanelView = loop.panel.PanelView;
  // 1.2. Conversation Window
  var IncomingCallView = loop.conversation.IncomingCallView;
  var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
  var CallFailedView = loop.conversationViews.CallFailedView;
  var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;

  // 2. Standalone webapp
  var HomeView = loop.webapp.HomeView;
  var UnsupportedBrowserView  = loop.webapp.UnsupportedBrowserView;
  var UnsupportedDeviceView   = loop.webapp.UnsupportedDeviceView;
  var CallUrlExpiredView      = loop.webapp.CallUrlExpiredView;
  var GumPromptConversationView = loop.webapp.GumPromptConversationView;
  var WaitingConversationView = loop.webapp.WaitingConversationView;
  var StartConversationView   = loop.webapp.StartConversationView;
  var FailedConversationView  = loop.webapp.FailedConversationView;
  var EndedConversationView   = loop.webapp.EndedConversationView;
  var StandaloneRoomView      = loop.standaloneRoomViews.StandaloneRoomView;

  // 3. Shared components
  var ConversationToolbar = loop.shared.views.ConversationToolbar;
  var ConversationView = loop.shared.views.ConversationView;
  var FeedbackView = loop.shared.views.FeedbackView;

  // Store constants
  var ROOM_STATES = loop.store.ROOM_STATES;
  var FEEDBACK_STATES = loop.store.FEEDBACK_STATES;

  // Local helpers
  function returnTrue() {
    return true;
  }

  function returnFalse() {
    return false;
  }

  function noop(){}

  // Feedback API client configured to send data to the stage input server,
  // which is available at https://input.allizom.org
  var stageFeedbackApiClient = new loop.FeedbackAPIClient(
    "https://input.allizom.org/api/v1/feedback", {
      product: "Loop"
    }
  );

  var dispatcher = new loop.Dispatcher();
  var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {
    mozLoop: navigator.mozLoop,
    sdkDriver: {}
  });
  var roomStore = new loop.store.RoomStore(dispatcher, {
    mozLoop: navigator.mozLoop
  });
  var feedbackStore = new loop.store.FeedbackStore(dispatcher, {
    feedbackClient: stageFeedbackApiClient
  });

  // Local mocks

  var mockMozLoopRooms = _.extend({}, navigator.mozLoop);
  mockMozLoopRooms.roomsEnabled = true;

  var mockContact = {
    name: ["Mr Smith"],
    email: [{
      value: "smith@invalid.com"
    }]
  };

  var mockClient = {
    requestCallUrl: noop,
    requestCallUrlInfo: noop
  };

  var mockSDK = {};

  var mockConversationModel = new loop.shared.models.ConversationModel({
    callerId: "Mrs Jones",
    urlCreationDate: (new Date() / 1000).toString()
  }, {
    sdk: mockSDK
  });
  mockConversationModel.startSession = noop;

  var mockWebSocket = new loop.CallConnectionWebSocket({
    url: "fake",
    callId: "fakeId",
    websocketToken: "fakeToken"
  });

  var notifications = new loop.shared.models.NotificationCollection();
  var errNotifications = new loop.shared.models.NotificationCollection();
  errNotifications.add({
    level: "error",
    message: "Could Not Authenticate",
    details: "Did you change your password?",
    detailsButtonLabel: "Retry",
  });

  var SVGIcon = React.createClass({
    render: function() {
      return (
        <span className="svg-icon" style={{
          "background-image": "url(/content/shared/img/icons-16x16.svg#" + this.props.shapeId + ")"
        }} />
      );
    }
  });

  var SVGIcons = React.createClass({
    shapes: [
      "audio", "audio-hover", "audio-active", "block",
      "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
      "contacts-active", "copy", "checkmark", "google", "google-hover",
      "google-active", "history", "history-hover", "history-active", "leave",
      "precall", "precall-hover", "precall-active", "settings", "settings-hover",
      "settings-active", "tag", "tag-hover", "tag-active", "trash", "unblock",
      "unblock-hover", "unblock-active", "video", "video-hover", "video-active"
    ],

    render: function() {
      return (
        <div className="svg-icon-list">{
          this.shapes.map(function(shapeId, i) {
            return <div key={i} className="svg-icon-entry">
              <p><SVGIcon shapeId={shapeId} /></p>
              <p>{shapeId}</p>
            </div>;
          }, this)
        }</div>
      );
    }
  });

  var Example = React.createClass({
    makeId: function(prefix) {
      return (prefix || "") + this.props.summary.toLowerCase().replace(/\s/g, "-");
    },

    render: function() {
      var cx = React.addons.classSet;
      return (
        <div className="example">
          <h3 id={this.makeId()}>
            {this.props.summary}
            <a href={this.makeId("#")}>&nbsp;¶</a>
          </h3>
          <div className={cx({comp: true, dashed: this.props.dashed})}
               style={this.props.style || {}}>
            {this.props.children}
          </div>
        </div>
      );
    }
  });

  var Section = React.createClass({
    render: function() {
      return (
        <section id={this.props.name}>
          <h1>{this.props.name}</h1>
          {this.props.children}
        </section>
      );
    }
  });

  var ShowCase = React.createClass({
    render: function() {
      return (
        <div className="showcase">
          <header>
            <h1>Loop UI Components Showcase</h1>
            <nav className="showcase-menu">{
              React.Children.map(this.props.children, function(section) {
                return (
                  <a className="btn btn-info" href={"#" + section.props.name}>
                    {section.props.name}
                  </a>
                );
              })
            }</nav>
          </header>
          {this.props.children}
        </div>
      );
    }
  });

  var App = React.createClass({
    render: function() {
      return (
        <ShowCase>
          <Section name="PanelView">
            <p className="note">
              <strong>Note:</strong> 332px wide.
            </p>
            <Example summary="Call URL retrieved" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={notifications}
                         callUrl="http://invalid.example.url/"
                         mozLoop={navigator.mozLoop}
                         dispatcher={dispatcher}
                         roomStore={roomStore} />
            </Example>
            <Example summary="Call URL retrieved - authenticated" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={notifications}
                         callUrl="http://invalid.example.url/"
                         userProfile={{email: "test@example.com"}}
                         mozLoop={navigator.mozLoop}
                         dispatcher={dispatcher}
                         roomStore={roomStore} />
            </Example>
            <Example summary="Pending call url retrieval" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={notifications}
                         mozLoop={navigator.mozLoop}
                         dispatcher={dispatcher}
                         roomStore={roomStore} />
            </Example>
            <Example summary="Pending call url retrieval - authenticated" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={notifications}
                         userProfile={{email: "test@example.com"}}
                         mozLoop={navigator.mozLoop}
                         dispatcher={dispatcher}
                         roomStore={roomStore} />
            </Example>
            <Example summary="Error Notification" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={errNotifications}
                         mozLoop={navigator.mozLoop}
                         dispatcher={dispatcher}
                         roomStore={roomStore} />
            </Example>
            <Example summary="Error Notification - authenticated" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={errNotifications}
                         userProfile={{email: "test@example.com"}}
                         mozLoop={navigator.mozLoop}
                         dispatcher={dispatcher}
                         roomStore={roomStore} />
            </Example>
            <Example summary="Room list tab" dashed="true" style={{width: "332px"}}>
              <PanelView client={mockClient} notifications={notifications}
                         userProfile={{email: "test@example.com"}}
                         mozLoop={mockMozLoopRooms}
                         dispatcher={dispatcher}
                         roomStore={roomStore}
                         selectedTab="rooms" />
            </Example>
          </Section>

          <Section name="IncomingCallView">
            <Example summary="Default / incoming video call" dashed="true" style={{width: "260px", height: "254px"}}>
              <div className="fx-embedded">
                <IncomingCallView model={mockConversationModel}
                                  video={true} />
              </div>
            </Example>

            <Example summary="Default / incoming audio only call" dashed="true" style={{width: "260px", height: "254px"}}>
              <div className="fx-embedded">
                <IncomingCallView model={mockConversationModel}
                                  video={false} />
              </div>
            </Example>
          </Section>

          <Section name="IncomingCallView-ActiveState">
            <Example summary="Default" dashed="true" style={{width: "260px", height: "254px"}}>
              <div className="fx-embedded" >
                <IncomingCallView  model={mockConversationModel}
                                   showMenu={true} />
              </div>
            </Example>
          </Section>

          <Section name="ConversationToolbar">
            <h2>Desktop Conversation Window</h2>
            <div className="fx-embedded override-position">
              <Example summary="Default (260x265)" dashed="true">
                <ConversationToolbar video={{enabled: true}}
                                     audio={{enabled: true}}
                                     hangup={noop}
                                     publishStream={noop} />
              </Example>
              <Example summary="Video muted">
                <ConversationToolbar video={{enabled: false}}
                                     audio={{enabled: true}}
                                     hangup={noop}
                                     publishStream={noop} />
              </Example>
              <Example summary="Audio muted">
                <ConversationToolbar video={{enabled: true}}
                                     audio={{enabled: false}}
                                     hangup={noop}
                                     publishStream={noop} />
              </Example>
            </div>

            <h2>Standalone</h2>
            <div className="standalone override-position">
              <Example summary="Default">
                <ConversationToolbar video={{enabled: true}}
                                     audio={{enabled: true}}
                                     hangup={noop}
                                     publishStream={noop} />
              </Example>
              <Example summary="Video muted">
                <ConversationToolbar video={{enabled: false}}
                                     audio={{enabled: true}}
                                     hangup={noop}
                                     publishStream={noop} />
              </Example>
              <Example summary="Audio muted">
                <ConversationToolbar video={{enabled: true}}
                                     audio={{enabled: false}}
                                     hangup={noop}
                                     publishStream={noop} />
              </Example>
            </div>
          </Section>

          <Section name="GumPromptConversationView">
            <Example summary="Gum Prompt conversation view" dashed="true">
              <div className="standalone">
                <GumPromptConversationView />
              </div>
            </Example>
          </Section>

          <Section name="WaitingConversationView">
            <Example summary="Waiting conversation view (connecting)" dashed="true">
              <div className="standalone">
                <WaitingConversationView websocket={mockWebSocket}
                                         dispatcher={dispatcher} />
              </div>
            </Example>
            <Example summary="Waiting conversation view (ringing)" dashed="true">
              <div className="standalone">
                <WaitingConversationView websocket={mockWebSocket}
                                         dispatcher={dispatcher}
                                         callState="ringing"/>
              </div>
            </Example>
          </Section>

          <Section name="PendingConversationView (Desktop)">
            <Example summary="Connecting" dashed="true"
                     style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <DesktopPendingConversationView callState={"gather"}
                                                contact={mockContact}
                                                dispatcher={dispatcher} />
              </div>
            </Example>
          </Section>

          <Section name="CallFailedView">
            <Example summary="Call Failed" dashed="true"
                     style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <CallFailedView dispatcher={dispatcher} />
              </div>
            </Example>
            <Example summary="Call Failed — with call URL error" dashed="true"
                     style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <CallFailedView dispatcher={dispatcher} emailLinkError={true} />
              </div>
            </Example>
          </Section>

          <Section name="StartConversationView">
            <Example summary="Start conversation view" dashed="true">
              <div className="standalone">
                <StartConversationView conversation={mockConversationModel}
                                       client={mockClient}
                                       notifications={notifications} />
              </div>
            </Example>
          </Section>

          <Section name="FailedConversationView">
            <Example summary="Failed conversation view" dashed="true">
              <div className="standalone">
                <FailedConversationView conversation={mockConversationModel}
                                        client={mockClient}
                                        notifications={notifications} />
              </div>
            </Example>
          </Section>

          <Section name="ConversationView">
            <Example summary="Desktop conversation window" dashed="true"
                     style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <ConversationView sdk={mockSDK}
                                  model={mockConversationModel}
                                  video={{enabled: true}}
                                  audio={{enabled: true}} />
              </div>
            </Example>

            <Example summary="Desktop conversation window large" dashed="true">
              <div className="breakpoint" data-breakpoint-width="800px"
                data-breakpoint-height="600px">
                <div className="fx-embedded">
                  <ConversationView sdk={mockSDK}
                    video={{enabled: true}}
                    audio={{enabled: true}}
                    model={mockConversationModel} />
                </div>
              </div>
            </Example>

            <Example summary="Desktop conversation window local audio stream"
                     dashed="true" style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <ConversationView sdk={mockSDK}
                                  video={{enabled: false}}
                                  audio={{enabled: true}}
                                  model={mockConversationModel} />
              </div>
            </Example>

            <Example summary="Standalone version">
              <div className="standalone">
                <ConversationView sdk={mockSDK}
                                  video={{enabled: true}}
                                  audio={{enabled: true}}
                                  model={mockConversationModel} />
              </div>
            </Example>
          </Section>

          <Section name="ConversationView-640">
            <Example summary="640px breakpoint for conversation view">
              <div className="breakpoint"
                   style={{"text-align":"center"}}
                   data-breakpoint-width="400px"
                   data-breakpoint-height="780px">
                <div className="standalone">
                  <ConversationView sdk={mockSDK}
                                    video={{enabled: true}}
                                    audio={{enabled: true}}
                                    model={mockConversationModel} />
                </div>
              </div>
            </Example>
          </Section>

          <Section name="ConversationView-LocalAudio">
            <Example summary="Local stream is audio only">
              <div className="standalone">
                <ConversationView sdk={mockSDK}
                                  video={{enabled: false}}
                                  audio={{enabled: true}}
                                  model={mockConversationModel} />
              </div>
            </Example>
          </Section>

          <Section name="FeedbackView">
            <p className="note">
              <strong>Note:</strong> For the useable demo, you can access submitted data at&nbsp;
              <a href="https://input.allizom.org/">input.allizom.org</a>.
            </p>
            <Example summary="Default (useable demo)" dashed="true" style={{width: "260px"}}>
              <FeedbackView feedbackStore={feedbackStore} />
            </Example>
            <Example summary="Detailed form" dashed="true" style={{width: "260px"}}>
              <FeedbackView feedbackStore={feedbackStore} feedbackState={FEEDBACK_STATES.DETAILS} />
            </Example>
            <Example summary="Thank you!" dashed="true" style={{width: "260px"}}>
              <FeedbackView feedbackStore={feedbackStore} feedbackState={FEEDBACK_STATES.SENT} />
            </Example>
          </Section>

          <Section name="CallUrlExpiredView">
            <Example summary="Firefox User">
              <CallUrlExpiredView helper={{isFirefox: returnTrue}} />
            </Example>
            <Example summary="Non-Firefox User">
              <CallUrlExpiredView helper={{isFirefox: returnFalse}} />
            </Example>
          </Section>

          <Section name="EndedConversationView">
            <Example summary="Displays the feedback form">
              <div className="standalone">
                <EndedConversationView sdk={mockSDK}
                                       video={{enabled: true}}
                                       audio={{enabled: true}}
                                       conversation={mockConversationModel}
                                       feedbackStore={feedbackStore}
                                       onAfterFeedbackReceived={noop} />
              </div>
            </Example>
          </Section>

          <Section name="AlertMessages">
            <Example summary="Various alerts">
              <div className="alert alert-warning">
                <button className="close"></button>
                <p className="message">
                  The person you were calling has ended the conversation.
                </p>
              </div>
              <br />
              <div className="alert alert-error">
                <button className="close"></button>
                <p className="message">
                  The person you were calling has ended the conversation.
                </p>
              </div>
            </Example>
          </Section>

          <Section name="HomeView">
            <Example summary="Standalone Home View">
              <div className="standalone">
                <HomeView />
              </div>
            </Example>
          </Section>


          <Section name="UnsupportedBrowserView">
            <Example summary="Standalone Unsupported Browser">
              <div className="standalone">
                <UnsupportedBrowserView helper={{isFirefox: returnFalse}}/>
              </div>
            </Example>
          </Section>

          <Section name="UnsupportedDeviceView">
            <Example summary="Standalone Unsupported Device">
              <div className="standalone">
                <UnsupportedDeviceView />
              </div>
            </Example>
          </Section>

          <Section name="DesktopRoomConversationView">
            <Example summary="Desktop room conversation (invitation)" dashed="true"
                     style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <DesktopRoomConversationView
                  roomStore={roomStore}
                  dispatcher={dispatcher}
                  roomState={ROOM_STATES.INIT} />
              </div>
            </Example>

            <Example summary="Desktop room conversation" dashed="true"
                     style={{width: "260px", height: "265px"}}>
              <div className="fx-embedded">
                <DesktopRoomConversationView
                  roomStore={roomStore}
                  dispatcher={dispatcher}
                  roomState={ROOM_STATES.HAS_PARTICIPANTS} />
              </div>
            </Example>
          </Section>

          <Section name="StandaloneRoomView">
            <Example summary="Standalone room conversation (ready)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  roomState={ROOM_STATES.READY}
                  helper={{isFirefox: returnTrue}} />
              </div>
            </Example>

            <Example summary="Standalone room conversation (joined)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  roomState={ROOM_STATES.JOINED}
                  helper={{isFirefox: returnTrue}} />
              </div>
            </Example>

            <Example summary="Standalone room conversation (has-participants)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  roomState={ROOM_STATES.HAS_PARTICIPANTS}
                  helper={{isFirefox: returnTrue}} />
              </div>
            </Example>

            <Example summary="Standalone room conversation (full - FFx user)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  roomState={ROOM_STATES.FULL}
                  helper={{isFirefox: returnTrue}} />
              </div>
            </Example>

            <Example summary="Standalone room conversation (full - non FFx user)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  roomState={ROOM_STATES.FULL}
                  helper={{isFirefox: returnFalse}} />
              </div>
            </Example>

            <Example summary="Standalone room conversation (feedback)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  feedbackStore={feedbackStore}
                  roomState={ROOM_STATES.ENDED}
                  helper={{isFirefox: returnFalse}} />
              </div>
            </Example>

            <Example summary="Standalone room conversation (failed)">
              <div className="standalone">
                <StandaloneRoomView
                  dispatcher={dispatcher}
                  activeRoomStore={activeRoomStore}
                  roomState={ROOM_STATES.FAILED}
                  helper={{isFirefox: returnFalse}} />
              </div>
            </Example>
          </Section>

          <Section name="SVG icons preview">
            <Example summary="16x16">
              <SVGIcons />
            </Example>
          </Section>

        </ShowCase>
      );
    }
  });

  /**
   * Render components that have different styles across
   * CSS media rules in their own iframe to mimic the viewport
   * */
  function _renderComponentsInIframes() {
    var parents = document.querySelectorAll('.breakpoint');
    [].forEach.call(parents, appendChildInIframe);

    /**
     * Extracts the component from the DOM and appends in the an iframe
     *
     * @type {HTMLElement} parent - Parent DOM node of a component & iframe
     * */
    function appendChildInIframe(parent) {
      var styles     = document.querySelector('head').children;
      var component  = parent.children[0];
      var iframe     = document.createElement('iframe');
      var width      = parent.dataset.breakpointWidth;
      var height     = parent.dataset.breakpointHeight;

      iframe.style.width  = width;
      iframe.style.height = height;

      parent.appendChild(iframe);
      iframe.src    = "about:blank";
      // Workaround for bug 297685
      iframe.onload = function () {
        var iframeHead = iframe.contentDocument.querySelector('head');
        iframe.contentDocument.documentElement.querySelector('body')
                                              .appendChild(component);

        [].forEach.call(styles, function(style) {
          iframeHead.appendChild(style.cloneNode(true));
        });

      };
    }
  }

  window.addEventListener("DOMContentLoaded", function() {
    React.renderComponent(<App />, document.body);

    _renderComponentsInIframes();

    // Put the title back, in case views changed it.
    document.title = "Loop UI Components Showcase";
  });

})();
