//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Combine
import Foundation
import UIKit

enum HomeScreenViewModelAction {
    case presentRoom(roomIdentifier: String)
    case presentSessionVerificationScreen
    case presentSettingsScreen
    case presentInviteFriendsScreen
    case presentFeedbackScreen
    case signOut
}

enum HomeScreenViewUserMenuAction {
    case settings
    case inviteFriends
    case feedback
    case signOut
}

enum HomeScreenViewAction {
    case selectRoom(roomIdentifier: String)
    case userMenu(action: HomeScreenViewUserMenuAction)
    case verifySession
    case skipSessionVerification
    case updateVisibleItemRange(range: Range<Int>, isScrolling: Bool)
}

enum HomeScreenRoomListMode: CustomStringConvertible {
    case skeletons
    case rooms
    
    var description: String {
        switch self {
        case .rooms:
            return "Showing rooms"
        case .skeletons:
            return "Showing placeholders"
        }
    }
}

struct HomeScreenViewState: BindableState {
    var userID: String
    var userDisplayName: String?
    var userAvatarURL: URL?
    
    var showSessionVerificationBanner = false
    
    var rooms: [HomeScreenRoom] = []
    
    var roomListMode: HomeScreenRoomListMode = .skeletons
    
    var visibleRooms: [HomeScreenRoom] {
        if roomListMode == .skeletons {
            return placeholderRooms
        }
        
        if bindings.searchQuery.isEmpty {
            return rooms
        }
        
        return rooms.lazy.filter { $0.name.localizedStandardContains(bindings.searchQuery) }
    }
    
    var bindings = HomeScreenViewStateBindings()
    
    var placeholderRooms: [HomeScreenRoom] {
        (1...10).map { _ in
            HomeScreenRoom.placeholder()
        }
    }
}

struct HomeScreenViewStateBindings {
    var searchQuery = ""
    
    var alertInfo: AlertInfo<UUID>?
}

struct HomeScreenRoom: Identifiable, Equatable {
    static let placeholderLastMessage = AttributedString("Hidden last message")
    
    enum LastMessage: Equatable {
        case loaded(AttributedString)
        case loading
        case unknown
        
        init(attributedString: AttributedString?, isLoading: Bool) {
            if let message = attributedString, !message.characters.isEmpty {
                self = .loaded(message)
            } else if isLoading {
                self = .loading
            } else {
                self = .unknown
            }
        }
    }
    
    /// The list item identifier can be a real room identifier, a custom one for invalidated entries
    /// or a completely unique one for empty items and skeletons
    let id: String
    
    /// The real room identifier this item points to
    let roomId: String?
    
    var name = ""
    
    var hasUnreads = false
    
    var timestamp: String?
    
    var lastMessage: LastMessage
    
    var avatarURL: URL?
    
    var isPlaceholder = false
    
    static func placeholder() -> HomeScreenRoom {
        HomeScreenRoom(id: UUID().uuidString,
                       roomId: nil,
                       name: "Placeholder room name",
                       hasUnreads: false,
                       timestamp: "Now",
                       lastMessage: .loading,
                       isPlaceholder: true)
    }
}
