/* global onPopoutClose, Twitch, _ */

import Controller from 'ember-controller';
import RoomModel from 'web-client/models/room';
import ContextBoundTasksMixin from 'web-client/mixins/context-bound-tasks';
import injectController from 'ember-controller/inject';
import injectService from 'ember-service/inject';
import computed from 'ember-computed';
import observer from 'ember-metal/observer';

export default Controller.extend(ContextBoundTasksMixin, {
  globals: injectService(),
  disableGroupChat: computed.alias('globals.disableGroupChat'),
  application: injectController(),
  session: injectService(),
  tmi: injectService(),
  tracking: injectService(),
  conversations: injectService('twitch-conversations/conversations'),

  init() {
    this._super(...arguments);

    this.isChatHidden = false;

    this.set('privateGroupRooms', RoomModel.find('group').load());

    this.get('tmi.tmiSession').then((tmiSession) => {
      if (this.isDestroyed) { return; }

      this.set('tmiSession', tmiSession);

      if (!this.get('disableGroupChat')) {
        tmiSession.on('invited', (invitation) => {
          if (this.isDestroyed) { return; }

          if (!this.get('showList')) {
            invitation.room = RoomModel.findOne(invitation.ircChannel);
            this.set('invitation', invitation);
          }
        });
      }

      this._flashDisabledHandler = () => {
        if (this.isDestroyed) { return; }
        this.set('flashDisabled', true);
      };

      tmiSession.on('flashdisabled', this._flashDisabledHandler);
    });
  },

  /** Properties, Computed Properties, and Observers */

  showList: false,
  showCreateRoom: false,
  showInviteUser: false,
  showViewerList: false,
  createRoomName: '',
  createRoomPublic: true,
  inviteUserName: '',
  isLoggedIn: Twitch.user.isLoggedIn(),
  flashDisabled: null, // Used to set disabled attr, so needs to be null/undefined rather than falsey

  connectedPrivateGroupRooms: computed('privateGroupRooms.@each.invitationAccepted', function () {
    return this.get('privateGroupRooms').filter(function (item) {
      return item.get('invitationAccepted');
    });
  }),

  invitedPrivateGroupRooms: computed('privateGroupRooms.@each.invitationPending', function () {
    return this.get('privateGroupRooms').filter(function (item) {
      return item.get('invitationPending');
    });
  }),

  notificationsCount: computed('currentRoom', 'currentChannelRoom', 'currentChannelRoom.unreadCount', 'invitedPrivateGroupRooms.length',
    'connectedPrivateGroupRooms.@each.unreadCount', function () {
    let currentRoom = this.get('currentRoom');
    let notificationsCount = this.get('invitedPrivateGroupRooms.length') || 0;
    if (currentRoom !== this.get('currentChannelRoom') && this.get('currentChannelRoom.unreadCount')) {
      notificationsCount++;
    }
    _.each(this.get('connectedPrivateGroupRooms') || [], function (room) {
      if (currentRoom !== room && room.get('unreadCount')) {
        notificationsCount++;
      }
    });
    return notificationsCount;
  }),

  _triggerRefreshOnDeletedRoom: observer('privateGroupRooms.@each.deleted', function () {
    let someRoomsAreDeleted = _.some(this.get('privateGroupRooms.content') || [], function (room) {
      return room.get('deleted');
    });
    if (someRoomsAreDeleted) {
      this.refresh();
    }
  }),

  _kickUserFromRoomNoLongerInList: observer('privateGroupRooms.[]', function () {
    let currentRoom = this.get('currentRoom'),
        currentChannelRoom = this.get('currentChannelRoom'),
        currentRoomIsAnActiveGroupRoom = _.contains(this.get('privateGroupRooms.content') || [], currentRoom),
        currentRoomIsTheCurrentChannel = currentChannelRoom && currentChannelRoom === currentRoom;
    if (!currentRoomIsAnActiveGroupRoom && !currentRoomIsTheCurrentChannel) {
      this.blurRoom();
      if (!this.get('showList')) {
        this.send('toggleMode');
      }
    }
  }),

  /** Public Functions */

  refresh: function () {
    this.get('privateGroupRooms').load();
  },

  /** Sets the current channel's chat room.  Currently also focuses it. */
  setCurrentChannelRoom: function (id) {
    this.removeCurrentChannelRoom();
    if (id) {
      let currentChannelRoom = RoomModel.findOne(id);
      this.set('currentChannelRoom', currentChannelRoom);
      this.focusRoom(currentChannelRoom);
      currentChannelRoom.checkForHostMode();
    }
  },

  /** Disconnects and cleans up thecurrent channel's chat room. */
  removeCurrentChannelRoom: function () {
    this.set('conversations.currentRoomName', null);
    let currentChannelRoom = this.get('currentChannelRoom');
    if (this.get('currentRoom') === currentChannelRoom) {
      this.blurRoom();
    }
    if (currentChannelRoom) {
      currentChannelRoom.destroy();
    }
    this.set('currentChannelRoom', null);
  },

  focusRoom: function (room) {
    this.set('currentRoom', room);

    let nameSource = room.get('channel') || room.get('tmiRoom');
    let roomName = nameSource.display_name || nameSource.displayName;
    this.set('conversations.currentRoomName', roomName);
  },

  blurRoom: function () {
    this.set('currentRoom', null);
    if (this.get('conversations.currentRoomName')) {
      this.set('conversations.currentRoomName', null);
    }
  },

  /** Action Handlers */

  actions: {
    roomClick(room) {
      this.toggleProperty('showList');
      this.focusRoom(room);
    },

    toggleViewerList() {
      this.toggleProperty('showViewerList');
      if (this.get('showViewerList')) {
        this.get('currentRoom.viewers').load();
      }
    },

    toggleMode() {
      let room = this.get('currentRoom');
      this.set('showCreateRoom', false);
      this.set('showInviteUser', false);
      this.set('invitation', null);
      this.toggleProperty('showList');
      if (this.get('showList')) {
        this.refresh();
        if (room) {
          room.resetUnreadCount();
        }
      }
    },

    toggleCreateRoom() {
      if (this.isLoggedIn) {
        this.toggleProperty('showCreateRoom');
      } else {
        this.send('handleNotLoggedIn', {mpSourceAction: "chat"});
      }
    },

    toggleInviteUser() {
      this.toggleProperty('showInviteUser');
    },

    createRoom() {
      if (this.get('createRoomName') && !this.get('createRoomInProgress')) {
        this.set('createRoomInProgress', true);
        let options = {
          name: this.get('createRoomName'),
          publicInvitesEnabled: this.get('createRoomPublic')
        };
        RoomModel.createNewTmiRoom(this.get('tmi.tmiSession'), this.get('session'), options).then((tmiRoom) => {
          this.trackCreateRoom();
          if (this.isDestroyed) {return;}
          let room = RoomModel.findOne(tmiRoom.name);
          this.set('showCreateRoom', false);
          this.set('createRoomName', '');
          this.set('createRoomFailureMessage', '');
          this.set('createRoomInProgress', false);
          this.focusRoom(room);
          if (this.get('showList')) {
            this.send('toggleMode');
          }
        }, () => {
          this.set('createRoomFailureMessage', 'Room creation failed.');
          this.set('createRoomInProgress', false);
        });
      }
    },

    invitationClick() {
      this.send('toggleMode');
    },

    inviteUser() {
      let self = this,
          room = this.get('currentRoom'),
          success = function () {
            self.set('showInviteUser', false);
            self.set('inviteUserName', '');
            self.set('inviteUserFailureMessage', '');
            self.set('inviteUserInProgress', false);
          },
          failure = function () {
            self.set('inviteUserFailureMessage', 'Please enter a valid username.');
            self.set('inviteUserInProgress', false);
          };
      if (room && !this.get('inviteUserInProgress')) {
        this.set('inviteUserInProgress', true);
        let inviteUserName = this.get('inviteUserName');
        room.invite(inviteUserName).then(() => {
          if (this.isDestroyed) { return; }
          success();
        }, error => {
          if (this.isDestroyed) { return; }
          if (error === 'unauthorized') {
            success();
          } else {
            failure();
          }
        });
      }
    },

    acceptInvitation(room) {
      room.acceptInvite().then(() => {
        this.runTask(() => {
          this.focusRoom(room);
          this.send('toggleMode');
        });
      }).catch(() => {

      });
    },

    blockUserAndRejectRoom(user) {
      if (user) {
        _.each(this.get('privateGroupRooms.content') || [], function (room) {
          if (room.get('inviter') === user && !room.get('invitationAccepted')) {
            room.rejectInvite();
          }
        });
        RoomModel.rejectUser(this.get('tmi.tmiSession'), {user: user});
      }
    },

    rejectInvitation(room) {
      room.rejectInvite().then(() => {

      }).catch(() => {
        /** If the reject failed, perhaps it's because we're looking at a stale list for some reason. */
        this.runTask(() => {
          this.refresh();
        });
      });
    },

    leaveGroupRoom(room) {
      room.del().catch(function () {
        /* Silence Errors */
      });
    },

    hideChat() {
      this.set('isChatHidden', true);
      let currentRoom = this.get('currentChannelRoom');
      if (currentRoom) {
        currentRoom.exit();
      }
      _.each(this.get('connectedPrivateGroupRooms') || [], function (room) {
        room.exit();
      });
    },

    popout() {
      this.send('hideChat');
      let popout = this.openPopout();
      this.set('popout', popout);
      popout.focus();
      this.runTask(() => {
        onPopoutClose(popout, () => {
          this.runTask(() => {
            this.send('show');
          });
        });
      });
    },

    show() {
      this.set('isChatHidden', false);
      let currentRoom = this.get('currentChannelRoom');
      if (currentRoom && !currentRoom.tmiRoom._roomConn._hasEntered) {
        this.set('currentRoom.isLoading', true);
        currentRoom.enter();
      }
      _.each(this.get('connectedPrivateGroupRooms') || [], function (room) {
        room.enter();
      });
    }
  },

  /** Private Helper Functions */

  openPopout() {
    let roomId = this.get('currentRoom.id');
    return window.open(
      `/${roomId}/chat?popout=`,
      '_blank',
      'right=50,top=50,width=400,height=600,resizable=yes,scrollbars=no,toolbar=no,location=no,directories=no,' +
      'status=no,menubar=no,copyhistory=no'
    );
  },

  trackCreateRoom() {
    let { isAuthenticated, userData } = this.get('session');
    if (isAuthenticated) {
      this.get('tracking').trackEvent({
        event: 'chat-create-room',
        data: {
          channel: this.get('currentChannelRoom.id'),
          turbo: !!userData.has_turbo,
          user_account_is_verified: userData.account_verified // eslint-disable-line camelcase
        }
      });
    }
  },

  /** Checks to allow a user to do certain actions */
  checkEligibility() {
    // This should check if turbo, partner and logged in.
    // This is currently being called by setCurrentChannelRoom, move if needed.
    if (this.isLoggedIn) {
      this.set('creationEligible', true);
    }
  },

  willDestroy() {
    if (this._flashDisabledHandler) {
      this.get('tmiSession').off('flashdisabled', this._flashDisabledHandler);
    }
    this._super(...arguments);
  }
});
