//
//  ComposeView.swift
//
//
//  Created by MainasuK Cirno on 2021-7-16.
//

import UIKit
import SwiftUI

public struct ComposeView: View {

    @EnvironmentObject var viewModel: ComposeViewModel
    @State var statusEditorViewWidth: CGFloat = .zero

    let horizontalMargin: CGFloat = 20

    public init() { }

    public var body: some View {
        GeometryReader { proxy in
            List {
                // Content Warning
                if viewModel.isContentWarningComposing {
                    ContentWarningEditorView(
                        contentWarningContent: $viewModel.contentWarningContent,
                        placeholder: viewModel.contentWarningPlaceholder
                    )
                    .padding(EdgeInsets(top: 6, leading: horizontalMargin, bottom: 6, trailing: horizontalMargin))
                    .background(viewModel.contentWarningBackgroundColor)
                    .transition(.opacity)
                    .listRow(backgroundColor: Color(viewModel.backgroundColor))
                }

                // Author
                StatusAuthorView(
                    avatarImageURL: viewModel.avatarImageURL,
                    name: viewModel.authorName,
                    username: viewModel.authorUsername
                )
                .padding(EdgeInsets(top: 20, leading: horizontalMargin, bottom: 16, trailing: horizontalMargin))
                .listRow(backgroundColor: Color(viewModel.backgroundColor))

                // Editor
                StatusEditorView(
                    string: $viewModel.statusContent,
                    placeholder: viewModel.statusPlaceholder,
                    width: statusEditorViewWidth,
                    attributedString: viewModel.statusContentAttributedString,
                    keyboardType: .twitter,
                    viewDidAppear: $viewModel.viewDidAppear
                )
                .frame(width: statusEditorViewWidth)
                .frame(minHeight: 100)
                .padding(EdgeInsets(top: 0, leading: horizontalMargin, bottom: 0, trailing: horizontalMargin))
                .listRow(backgroundColor: Color(viewModel.backgroundColor))

                // Attachments
                ForEach(viewModel.attachmentViewModels) { attachmentViewModel in
                    let descriptionBinding = Binding {
                        return attachmentViewModel.descriptionContent
                    } set: { newValue in
                        attachmentViewModel.descriptionContent = newValue
                    }

                    StatusAttachmentView(
                        image: attachmentViewModel.thumbnailImage,
                        descriptionPlaceholder: attachmentViewModel.descriptionPlaceholder,
                        description: descriptionBinding,
                        errorPrompt: attachmentViewModel.errorPrompt,
                        errorPromptImage: attachmentViewModel.errorPromptImage,
                        isUploading: attachmentViewModel.isUploading,
                        progressViewTintColor: attachmentViewModel.progressViewTintColor,
                        removeButtonAction: {
                            self.viewModel.removeAttachmentViewModel(attachmentViewModel)
                        }
                    )
                }
                .padding(EdgeInsets(top: 16, leading: horizontalMargin, bottom: 0, trailing: horizontalMargin))
                .fixedSize(horizontal: false, vertical: true)
                .listRow(backgroundColor: Color(viewModel.backgroundColor))

                // bottom padding
                Color.clear
                    .frame(height: viewModel.toolbarHeight + 20)
                    .listRow(backgroundColor: Color(viewModel.backgroundColor))
            }   // end List
            .listStyle(.plain)
            .introspectTableView(customize: { tableView in
                // tableView.keyboardDismissMode = .onDrag
                tableView.verticalScrollIndicatorInsets.bottom = viewModel.toolbarHeight
            })
            .preference(
                key: ComposeListViewFramePreferenceKey.self,
                value: proxy.frame(in: .local)
            )
            .onPreferenceChange(ComposeListViewFramePreferenceKey.self) { frame in
                var frame = frame
                frame.size.width = frame.width - 2 * horizontalMargin
                statusEditorViewWidth = frame.width
            }   // end List
            .introspectTableView(customize: { tableView in
                tableView.backgroundColor = .clear
            })
            .overrideBackground(color: Color(viewModel.backgroundColor))
        }   // end GeometryReader
    }   // end body
}

struct ComposeListViewFramePreferenceKey: PreferenceKey {
    static var defaultValue: CGRect = .zero
    static func reduce(value: inout CGRect, nextValue: () -> CGRect) { }
}

extension View {
    // hack for separator line
    @ViewBuilder
    func listRow(backgroundColor: Color) -> some View {
        // expand list row to edge (set inset)
        // then hide the separator
        if #available(iOS 15, *) {
            frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
                .listRowInsets(EdgeInsets(top: -1, leading: -1, bottom: -1, trailing: -1))
                .background(backgroundColor)
                .listRowSeparator(.hidden)      // new API
        } else {
            frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
                .listRowInsets(EdgeInsets(top: -1, leading: -1, bottom: -1, trailing: -1))  // separator line hidden magic
                .background(backgroundColor)
        }
    }
    
    @ViewBuilder
    func overrideBackground(color: Color) -> some View {
        background(color.ignoresSafeArea())
    }
}


struct ComposeView_Previews: PreviewProvider {

    static let viewModel: ComposeViewModel = {
        let viewModel = ComposeViewModel()
        return viewModel
    }()

    static var previews: some View {
        ComposeView().environmentObject(viewModel)
    }
    
}
