<template>
  <v-list dense class="room-list">
    <v-list-item-group @change="roomChange" color="primary">

      <v-list-item v-if="showCreate" @click.stop="$emit('newroom')" class="room-list-room" :value="null">
        <v-list-item-avatar class="round" size="42" color="#d9d9d9">
          <v-icon size="11">$vuetify.icons.ic_new_room</v-icon>
        </v-list-item-avatar>
        <v-list-item-content>
          <v-list-item-title class="room-list-new-room">{{
            $t("menu.new_room")
          }}</v-list-item-title>
        </v-list-item-content>
      </v-list-item>

      <!-- invites -->
      <v-list-item :disabled="roomsProcessing[room.roomId]" v-for="room in invitedRooms" :key="room.roomId"
        :value="room" class="room-list-room">
        <v-list-item-avatar size="42" color="#d9d9d9">
          <v-img v-if="roomAvatar(room)" :src="roomAvatar(room)" />
          <span v-else class="white--text headline">{{
            room.name.substring(0, 1).toUpperCase()
          }}</span>
        </v-list-item-avatar>
        <v-list-item-content>
          <v-list-item-title class="room-list-name">{{ room.name }}</v-list-item-title>
          <v-list-item-subtitle>{{ room.topic }}</v-list-item-subtitle>
        </v-list-item-content>
        <v-list-item-action>
          <v-btn id="btn-accept" class="filled-button" depressed color="black" @click.stop="acceptInvitation(room)">{{
            $t("menu.join") }}</v-btn>
          <v-btn v-if="!room.isServiceNoticeRoom" id="btn-reject" class="filled-button" color="black" @click.stop="rejectInvitation(room)" text>{{
            $t("menu.ignore") }}</v-btn>
        </v-list-item-action>
      </v-list-item>

      <v-list-item v-for="room in joinedRooms" :key="room.roomId" :value="room" class="room-list-room">
        <v-list-item-avatar size="42" color="#d9d9d9" :class="[{'rounded-circle': isDirect(room)}]">
          <v-img v-if="roomAvatar(room)" :src="roomAvatar(room)" />
          <span v-else class="white--text headline">{{
            room.name.substring(0, 1).toUpperCase()
          }}</span>
        </v-list-item-avatar>
        <v-list-item-content>
          <v-list-item-title class="room-list-name">{{ room.name }}
            <!-- <v-icon class="ml-2 mb-1" size="10" v-if="isPublic(room)">$vuetify.icons.ic_public</v-icon> -->
          </v-list-item-title>
          <v-list-item-subtitle class="room-list-new-messages" v-if="notificationCount(room) > 0">
            {{ $t("room.room_list_new_messages", { count: notificationCount(room) }) }}
          </v-list-item-subtitle>
        </v-list-item-content>
        <v-list-item-action>
          <v-icon size="16" v-if="room.roomId == $matrix.currentRoomId">$vuetify.icons.ic_circle_filled</v-icon>
          <v-icon size="16" v-else>$vuetify.icons.ic_circle</v-icon>
        </v-list-item-action>
      </v-list-item>
    </v-list-item-group>
  </v-list>
</template>

<script>
import util from "../plugins/utils";
import Vue from "vue";

export default {
  name: "RoomList",

  props: {
    title: {
      type: String,
      default: "Rooms",
    },
    showInvites: {
      type: Boolean,
      default: false,
    },
    showCreate: {
      type: Boolean,
      default: false,
    },
  },

  data: () => ({
    /** A list of rooms currently processing some operation, like "join" or "reject" */
    roomsProcessing: {},
  }),

  computed: {
    invitedRooms() {
      return this.sortItemsOnName(this.$matrix.invites);
    },
    joinedRooms() {
      // show room with notification on top, followed by room decending order by active Timestamp
      return [...this.$matrix.joinedRooms].sort((a, b) => {
        if (this.notificationCount(a)) return -1;
        if (this.notificationCount(b)) return 1;
        return b.getLastActiveTimestamp() - a.getLastActiveTimestamp()
      });
    },
  },
  methods: {
    roomAvatar(room) {
      if (this.isDirect(room)) {
        if (room.avatar) {
          return room.avatar;
        }
        const membersNotMe = room.getMembers().filter(m => m.userId != this.$matrix.currentUserId);
        if (membersNotMe && membersNotMe.length == 1) {
          return membersNotMe[0].getAvatarUrl(
            this.$matrix.matrixClient.getHomeserverUrl(),
            42,
            42,
            "scale",
            true
          );
        }
      } else {
        return room.avatar;
      }
    },

    sortItemsOnName(items) {
      if (items == null) {
        return [];
      }
      return items.sort(function (a, b) {
        const titleA = a.name || a.summary.info.title;
        const titleB = b.name || b.summary.info.title;
        if (titleA == null) {
          return 1;
        } else if (titleB == null) {
          return -1;
        }
        return titleA.localeCompare(titleB);
      });
    },

    notificationCount(room) {
      return room.getUnreadNotificationCount("total") || 0;
    },

    acceptInvitation(room) {
      Vue.set(this.roomsProcessing, room.roomId, true);
      this.$matrix.matrixClient
        .joinRoom(room.roomId)
        .then((ignoredRoom) => {
          this.$nextTick(() => {
            this.$navigation.push(
              {
                name: "Chat",
                params: {
                  roomId: util.sanitizeRoomId(
                    room.getCanonicalAlias() || room.roomId
                  ),
                },
              },
              -1
            );
          });
        })
        .catch((err) => {
          console.error("Failed to accept invite: ", err);
        })
        .finally(() => {
          Vue.delete(this.roomsProcessing, room.roomId);
        });
    },

    rejectInvitation(room) {
      Vue.set(this.roomsProcessing, room.roomId, true);
      this.$matrix
        .leaveRoom(room.roomId)
        .catch((err) => {
          console.error("Failed to reject invite: ", err);
        })
        .finally(() => {
          Vue.delete(this.roomsProcessing, room.roomId);
        });
    },

    isPublic(room) {
      return this.$matrix.getRoomJoinRule(room) === "public"
    },

    isDirect(room) {
      return this.$matrix.isDirectRoom(room);
    },

    roomChange(room) {
      if (room == null || room == undefined || room == 0) {
        // Ignore, this is caused by "new room" etc.
        return;
      }
      if (room.isServiceNoticeRoom && room.selfMembership === "invite") {
        return; // Nothing should happen when click on invite to server notices room, just the "join" button is enabled.
      }
      this.$emit("close");
      this.$navigation.push(
        {
          name: "Chat",
          params: { roomId: util.sanitizeRoomId(room.roomId) },
        },
        -1
      );
  }
  },
};
</script>

<style lang="scss">
@import "@/assets/css/chat.scss";
</style>

<style lang="scss" scoped>
/** Align action buttons side to side */
.v-list-item__action--stack {
  flex-direction: row !important;
}
</style>