//
// Copyright 2021 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 SwiftUI

struct TemplateRoomChat: View {
    @Environment(\.theme) private var theme: ThemeSwiftUI
    
    @ObservedObject var viewModel: TemplateRoomChatViewModel.Context
    var presentedModally = false
    
    var body: some View {
        VStack {
            VStack {
                roomContent
            }.frame(maxHeight: .infinity)
            
            HStack {
                TextField(VectorL10n.roomMessageShortPlaceholder, text: $viewModel.messageInput)
                    .textFieldStyle(BorderedInputFieldStyle())
                if viewModel.viewState.sendButtonEnabled {
                    Button(action: {
                        viewModel.send(viewAction: .sendMessage)
                    }, label: {
                        Image(uiImage: Asset.Images.sendIcon.image)
                    })
                }
            }
            // When displaying/hiding the send button slide it on/off from the right side
            .animation(.easeOut(duration: 0.25))
            .transition(.move(edge: .trailing))
            .padding()
        }
        .background(theme.colors.background)
        .navigationTitle(viewModel.viewState.roomName ?? "Chat")
        .toolbar {
            ToolbarItem(placement: .primaryAction) {
                trailingToolBarButton
            }
        }
    }
    
    @ViewBuilder
    private var roomContent: some View {
        if case .notInitialized = viewModel.viewState.roomInitializationStatus {
            ProgressView()
                .progressViewStyle(CircularProgressViewStyle(tint: theme.colors.primaryContent))
                .accessibility(identifier: "loadingProgress")
        } else if case .failedToInitialize = viewModel.viewState.roomInitializationStatus {
            Text("Sorry, We failed to load the room.")
                .foregroundColor(theme.colors.primaryContent)
                .accessibility(identifier: "errorMessage")
        } else if viewModel.viewState.bubbles.isEmpty {
            Text("There are no messages in this room yet.")
                .foregroundColor(theme.colors.primaryContent)
                .accessibility(identifier: "errorMessage")
        } else {
            bubbleList
        }
    }
    
    private var bubbleList: some View {
        ScrollViewReader { reader in
            ScrollView {
                LazyVStack {
                    ForEach(viewModel.viewState.bubbles) { bubble in
                        TemplateRoomChatBubbleView(bubble: bubble)
                            .id(bubble.id)
                    }
                }
                .onAppear {
                    guard let lastBubbleId = viewModel.viewState.bubbles.last?.id
                    else { return }
                    reader.scrollTo(lastBubbleId, anchor: .bottom)
                }
                .onChange(of: itemCount) { _ in
                    guard let lastBubbleId = viewModel.viewState.bubbles.last?.id
                    else { return }
                    reader.scrollTo(lastBubbleId, anchor: .bottom)
                }
                // When the scroll content takes less than the screen space align at the top
                .frame(maxHeight: .infinity, alignment: .top)
            }
        }
    }
    
    @ViewBuilder
    private var trailingToolBarButton: some View {
        if presentedModally {
            Button(VectorL10n.done) {
                viewModel.send(viewAction: .done)
            }
        }
    }
    
    private var itemCount: Int {
        viewModel.viewState
            .bubbles
            .map(\.items)
            .map(\.count)
            .reduce(0, +)
    }
}

// MARK: - Previews

struct TemplateRoomChat_Previews: PreviewProvider {
    static let stateRenderer = MockTemplateRoomChatScreenState.stateRenderer
    static var previews: some View {
        stateRenderer.screenGroup(addNavigation: true)
    }
}
