<template>
  <v-list class="room-list">
    <v-list-item v-if="showCreate" @click.stop="$emit('newroom')" class="room-list-room" :value="null">
      <template v-slot:prepend>
        <v-avatar class="round" size="42" color="#d9d9d9">
          <v-icon size="11">$vuetify.icons.ic_new_room</v-icon>
        </v-avatar>
      </template>

      <v-list-item-title class="room-list-new-room">{{
        $t("menu.new_room")
      }}</v-list-item-title>
    </v-list-item>

    <!-- invites -->
    <v-list-item :disabled="roomsProcessing[room.roomId]" v-for="room in invitedRooms" :key="room.roomId"
      :value="room.roomId" class="room-list-room">
      <template v-slot:prepend>
        <v-avatar size="42" color="#d9d9d9">
          <AuthedImage v-if="roomAvatar(room)" :src="roomAvatar(room)" />
          <span v-else class="text-white headline">{{
            room.name.substring(0, 1).toUpperCase()
          }}</span>
        </v-avatar>
      </template>

      <v-list-item-title class="room-list-name">{{ room.name }}</v-list-item-title>
      <v-list-item-subtitle>{{ room.topic }}</v-list-item-subtitle>
      <template v-slot:append>
        <v-list-item-action>
          <v-btn id="btn-accept" class="filled-button" variant="flat" 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)" variant="text">{{
              $t("menu.ignore") }}</v-btn>
        </v-list-item-action>
      </template>
    </v-list-item>

    <!-- Knocked rooms -->
    <v-list-item :disabled="roomsProcessing[room.roomId]" v-for="room in knockedRooms" :key="room.roomId"
      :value="room.roomId" class="room-list-room">
      <template v-slot:prepend>
        <v-avatar size="42" color="#d9d9d9">
          <AuthedImage v-if="roomAvatar(room)" :src="roomAvatar(room)" />
          <span v-else class="text-white headline">{{
            room.name.substring(0, 1).toUpperCase()
          }}</span>
        </v-avatar>
      </template>

      <v-list-item-title class="room-list-name">{{ room.name }}</v-list-item-title>
      <v-list-item-subtitle>{{ room.topic }}</v-list-item-subtitle>
      <template v-slot:append>
        <v-list-item-action>
          <v-btn id="btn-reject" class="filled-button" color="black"
            @click.stop="rejectInvitation(room)" variant="text">{{
              $t("menu.cancel_knock") }}</v-btn>
        </v-list-item-action>
      </template>
    </v-list-item>

    <v-list-item v-for="room in joinedRooms" :key="room.roomId" :value="room.roomId"
      v-on:click="() => goToRoom(room)" class="room-list-room">
      <template v-slot:prepend>
        <v-avatar size="42" color="#d9d9d9" :class="[{ 'rounded-circle': isDirect(room) }]">
          <AuthedImage v-if="roomAvatar(room)" :src="roomAvatar(room)" />
          <span v-else class="text-white headline">{{
            room.name.substring(0, 1).toUpperCase()
          }}</span>
        </v-avatar>
      </template>
      <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>
      <template v-slot:append>
        <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>
      </template>
    </v-list-item>
  </v-list>
</template>

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

export default {
  name: "RoomList",
  components: { AuthedImage },
  props: {
    title: {
      type: String,
      default: "Rooms",
    },
    showInvites: {
      type: Boolean,
      default: false,
    },
    showCreate: {
      type: Boolean,
      default: false,
    },
  },

  data: () => ({
    currentRoomId: null,

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

  computed: {
    invitedRooms() {
      return this.sortItemsOnName(this.$matrix.invites);
    },
    knockedRooms() {
      return this.sortItemsOnName(this.$matrix.knockedRooms);
    },
    joinedRooms() {
      // show room with notification on top, followed by room decending order by active Timestamp
      let rooms = this.$matrix.joinedRooms;
      let upgradedRooms = rooms.filter((r) => r.currentState.getStateEvents("m.room.tombstone").length > 0);
      let normalRooms = rooms.filter((r) => r.currentState.getStateEvents("m.room.tombstone").length == 0);
      let normalRoomsId = normalRooms.map((r) => r.roomId);
      upgradedRooms.forEach(r => {
        const history = this.$matrix.matrixClient.getRoomUpgradeHistory(r.roomId, true, true);
        const successor = history[history.length - 1];
        if (!normalRoomsId.includes(successor.roomId)) {
          normalRoomsId.push(successor.roomId);
          normalRooms.push(successor);
        }
      });
      return [...normalRooms].sort((a, b) => {
        if (this.notificationCount(a)) return -1;
        if (this.notificationCount(b)) return 1;
        return b.getLastActiveTimestamp() - a.getLastActiveTimestamp()
      });
    },
  },
  methods: {
    goToRoom(room) {
      const events = room.currentState.getStateEvents("m.room.tombstone");
      if (events && events.length > 0) {
        const replacement_room = events[events.length - 1].getContent().replacement_room;
        this.$navigation.push(
        {
          name: "Join",
          params: { 
            roomId: utils.sanitizeRoomId(replacement_room), 
            join: true
          },
          query: this.$route.query
        },
        0
      );
      } else {
        this.currentRoomId = utils.sanitizeRoomId(room.roomId);
      }
    },
    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,
            false,
            this.$matrix.useAuthedMedia
          );
        }
      } 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) {
      this.roomsProcessing[room.roomId] = true;
      this.$matrix.matrixClient
        .joinRoom(room.roomId)
        .then((ignoredRoom) => {
          this.$nextTick(() => {
            this.$navigation.push(
              {
                name: "Chat",
                params: {
                  roomId: utils.sanitizeRoomId(
                    room.getCanonicalAlias() || room.roomId
                  ),
                },
              },
              -1
            );
          });
        })
        .catch((err) => {
          console.error("Failed to accept invite: ", err);
        })
        .finally(() => {
          delete this.roomsProcessing[room.roomId];
        });
    },

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

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

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

  watch: {
    currentRoomId() {
      if (this.currentRoomId == null || this.currentRoomId == undefined) {
        // Ignore, this is caused by "new room" etc.
        return;
      }
      this.$emit("close");
      this.$navigation.push(
        {
          name: "Chat",
          params: { roomId: utils.sanitizeRoomId(this.currentRoomId) },
        },
        -1
      );
    },
  },

};
</script>

<style lang="scss">
@use "@/assets/css/chat.scss" as *;
</style>

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