import QtQuick
import QtQuick.Layouts
import QtQuick.Controls.Basic as Control

import Linphone
import UtilsCpp 1.0
import ConstantsCpp 1.0
import SettingsCpp

ListView {
	id: mainItem
	height: contentHeight
	visible: contentHeight > 0
	clip: true	
	currentIndex: -1
	//keyNavigationWraps: true
	// rightMargin: 5 * DefaultStyle.dp

	property bool selectionEnabled: true
	property bool hoverEnabled: true
	// dots popup menu
	property bool contactMenuVisible: true
	// call, video call etc menu
	property bool actionLayoutVisible: false
	property bool initialHeadersVisible: true
	property bool displayNameCapitalization: true
	property bool showFavoritesOnly: false
	property bool showDefaultAddress: false
	property bool showLdapContacts: false
	property bool searchOnInitialization: false

	property var listProxy: MagicSearchProxy{}
	property alias hideListProxy: magicSearchProxy.hideListProxy

	// Model properties
	// set searchBarText without specifying a model to bold
	// matching names
	property string searchBarText
	property string searchText: searchBarText.length === 0 ? "*" : searchBarText
	property var aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend
	property var sourceFlags: LinphoneEnums.MagicSearchSource.Friends | ((searchText.length > 0 && searchText != "*") || SettingsCpp.syncLdapContacts ? LinphoneEnums.MagicSearchSource.LdapServers : 0)

	property ConferenceInfoGui confInfoGui

	property bool multiSelectionEnabled: false
	property list<string> selectedContacts
	property int selectedContactCount: selectedContacts.length

	property FriendGui selectedContact: model.getAt(currentIndex) || null

	signal contactStarredChanged()
	signal contactDeletionRequested(FriendGui contact)
	signal contactAddedToSelection(string address)
	signal contactRemovedFromSelection(string address)
	signal contactClicked(FriendGui contact)

	function selectContact(address) {
		var index = magicSearchProxy.findFriendIndexByAddress(address)
		if (index != -1) {
			mainItem.currentIndex = index
		}
		return index
	}
	function addContactToSelection(address) {
		if (multiSelectionEnabled) {
			var indexInSelection = selectedContacts.indexOf(address)
			if (indexInSelection == -1) {
				selectedContacts.push(address)
				contactAddedToSelection(address)
			}
		}
	}
	function removeContactFromSelection(indexInSelection) {
		var addressToRemove = selectedContacts[indexInSelection]
		if (indexInSelection != -1) {
			selectedContacts.splice(indexInSelection, 1)
			contactRemovedFromSelection(addressToRemove)
		}
	}
	function removeSelectedContactByAddress(address) {
		var index = selectedContacts.indexOf(address)
		if (index != -1) {
			selectedContacts.splice(index, 1)
			contactRemovedFromSelection(address)
		}
	}
	function haveAddress(address){
		var index = magicSearchProxy.findFriendIndexByAddress(address)
		return  index != -1
	}
	
	onCurrentIndexChanged: selectedContact = model.getAt(currentIndex) || null
	onCountChanged: selectedContact = model.getAt(currentIndex) || null
	
	Component.onCompleted: {
		if (confInfoGui) {
			for(var i = 0; i < confInfoGui.core.participants.length; ++i) {
				selectedContacts.push(confInfoGui.core.getParticipantAddressAt(i));
			}
		}
	}

	// strange behaviour with this lines
	// When a popup opens after clicking on a contact, the selected contact
	// changes because we lose focus on the list
	// onActiveFocusChanged: if(activeFocus && (!footerItem || !footerItem.activeFocus)) {
	// 	currentIndex = 0
	// }

	model: MagicSearchProxy {
		id: magicSearchProxy
		searchText: mainItem.searchText
		// This property is needed instead of playing on the delegate visibility
		// considering its starred status. Otherwise, the row in the list still
		// exists even if its delegate is not visible, and creates navigation issues
		showFavoritesOnly: mainItem.showFavoritesOnly
		aggregationFlag: mainItem.aggregationFlag
		parentProxy: mainItem.listProxy
		showLdapContacts: mainItem.showLdapContacts
		sourceFlags: mainItem.sourceFlags
		onFriendCreated: (index) => {
			mainItem.currentIndex = index
		}
		onInitialized: {
			if(mainItem.searchOnInitialization) magicSearchProxy.forceUpdate()
		}
	}

	Connections {
		target: SettingsCpp
		onLdapConfigChanged: {
			if (SettingsCpp.syncLdapContacts)
				magicSearchProxy.forceUpdate()
		}
	}

	Control.ScrollBar.vertical: ScrollBar {
		id: scrollbar
		active: true
		interactive: true
		// anchors.top: parent.top
		// anchors.bottom: parent.bottom
		// anchors.right: parent.right
	}
	Keys.onPressed: (event)=>{
		if(event.key == Qt.Key_Tab && !mainItem.itemAtIndex(mainItem.currentIndex).activeFocus){
			mainItem.itemAtIndex(mainItem.currentIndex).forceActiveFocus()
		}
	}
	delegate: FocusScope {
		id: itemDelegate
		height: 56 * DefaultStyle.dp
		width: mainItem.width
		property var previousItem : mainItem.model.count > 0 && index > 0 ? mainItem.model.getAt(index-1) : null
		property var previousDisplayName: previousItem ? previousItem.core.displayName : ""
		property var displayName: modelData.core.displayName

		Connections {
			enabled: modelData.core
			target: modelData.core
			function onStarredChanged() { mainItem.contactStarredChanged()}
		}
		Text {
			id: initial
			anchors.left: parent.left
			visible: mainItem.initialHeadersVisible && mainItem.model.sourceFlags != LinphoneEnums.MagicSearchSource.All
			anchors.verticalCenter: parent.verticalCenter
			anchors.rightMargin: 15 * DefaultStyle.dp
			verticalAlignment: Text.AlignVCenter
			width: 20 * DefaultStyle.dp
			opacity: (!previousItem || !previousDisplayName.toLocaleLowerCase(ConstantsCpp.DefaultLocale).startsWith(displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale))) ? 1 : 0
			text: displayName[0]
			color: DefaultStyle.main2_400
			font {
				pixelSize: 20 * DefaultStyle.dp
				weight: 500 * DefaultStyle.dp
				capitalization: Font.AllUppercase
			}
		}
		RowLayout {
			id: contactDelegate
			anchors.left: initial.visible ? initial.right : parent.left
			anchors.right: parent.right
			anchors.top: parent.top
			anchors.bottom: parent.bottom
			anchors.verticalCenter: parent.verticalCenter
			spacing: 16 * DefaultStyle.dp
			z: 1
			Avatar {
				Layout.leftMargin: 5 * DefaultStyle.dp
				Layout.preferredWidth: 45 * DefaultStyle.dp
				Layout.preferredHeight: 45 * DefaultStyle.dp
				contact: modelData
			}
			ColumnLayout {
				spacing: 0
				Text {
					text: UtilsCpp.boldTextPart(itemDelegate.displayName, mainItem.searchBarText)
					font{
						pixelSize: mainItem.showDefaultAddress ? 16 * DefaultStyle.dp : 14 * DefaultStyle.dp
						capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
						weight: mainItem.showDefaultAddress ? 800 * DefaultStyle.dp : 400 * DefaultStyle.dp
					}
					maximumLineCount: 1
					Layout.fillWidth: true
				}
				Text {
					maximumLineCount: 1
					visible: mainItem.showDefaultAddress
					text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(modelData.core.defaultAddress) : modelData.core.defaultAddress
					Layout.fillWidth: true
					Layout.topMargin: 2 * DefaultStyle.dp
					font {
						weight: 300 * DefaultStyle.dp
						pixelSize: 12 * DefaultStyle.dp
					}
				}
			}
			Item{Layout.fillWidth: true}
			RowLayout {
				id: actionsRow
				z: 1
				visible: actionButtons || friendPopup.visible || mainItem.multiSelectionEnabled
				spacing: visible ? 16 * DefaultStyle.dp : 0
				EffectImage {
					id: isSelectedCheck
					// visible: mainItem.multiSelectionEnabled && (mainItem.confInfoGui.core.getParticipantIndex(modelData.core.defaultAddress) != -1)
					visible: mainItem.multiSelectionEnabled && (mainItem.selectedContacts.indexOf(modelData.core.defaultAddress) != -1)
					Layout.preferredWidth: 24 * DefaultStyle.dp
					Layout.preferredHeight: 24 * DefaultStyle.dp
					imageSource: AppIcons.check
					colorizationColor: DefaultStyle.main1_500_main
					Connections {
						target: mainItem
						// onParticipantsChanged: isSelectedCheck.visible = mainItem.confInfoGui.core.getParticipantIndex(modelData.core.defaultAddress) != -1
						function onSelectedContactCountChanged(){ isSelectedCheck.visible = (mainItem.selectedContacts.indexOf(modelData.core.defaultAddress) != -1)}
					}
				}
				RowLayout{
					id: actionButtons
					visible: mainItem.actionLayoutVisible
					spacing: visible ? 10 * DefaultStyle.dp : 0
					Button {
						id: callButton
						Layout.preferredWidth: 45 * DefaultStyle.dp
						Layout.preferredHeight: 45 * DefaultStyle.dp
						icon.width: 24 * DefaultStyle.dp
						icon.height: 24 * DefaultStyle.dp
						icon.source: AppIcons.phone
						contentImageColor: DefaultStyle.main2_600
						focus: visible
						background: Rectangle {
							anchors.fill: parent
							radius: 40 * DefaultStyle.dp
							color: DefaultStyle.main2_200
						}
						onClicked: UtilsCpp.createCall(modelData.core.defaultAddress)
						KeyNavigation.right: chatButton
						KeyNavigation.left: chatButton
					}
					Button {
						id: chatButton
						visible: actionButtons.visible && !SettingsCpp.disableChatFeature
						Layout.preferredWidth: 45 * DefaultStyle.dp
						Layout.preferredHeight: 45 * DefaultStyle.dp
						icon.width: 24 * DefaultStyle.dp
						icon.height: 24 * DefaultStyle.dp
						icon.source: AppIcons.chatTeardropText
						focus: visible && !callButton.visible
						contentImageColor: DefaultStyle.main2_500main
						background: Rectangle {
							anchors.fill: parent
							radius: 40 * DefaultStyle.dp
							color: DefaultStyle.main2_200
						}
						KeyNavigation.right: callButton
						KeyNavigation.left: callButton
					}
				}
				PopupButton {
					id: friendPopup
					z: 1
					// Layout.rightMargin: 13 * DefaultStyle.dp
					Layout.alignment: Qt.AlignVCenter
					Layout.rightMargin: 8 * DefaultStyle.dp
					popup.x: 0
					popup.padding: 10 * DefaultStyle.dp
					hoverEnabled: mainItem.hoverEnabled
					visible: mainItem.contactMenuVisible && (contactArea.containsMouse || hovered || popup.opened) && (!mainItem.delegateButtons || mainItem.delegateButtons.length === 0)
					
					popup.contentItem: ColumnLayout {
						Button {
							text: $modelData.core.starred ? qsTr("Enlever des favoris") : qsTr("Mettre en favori")
							background: Item{}
							icon.source: modelData.core.starred ? AppIcons.heartFill : AppIcons.heart
							icon.width: 24 * DefaultStyle.dp
							icon.height: 24 * DefaultStyle.dp
							spacing: 10 * DefaultStyle.dp
							textSize: 14 * DefaultStyle.dp
							textWeight: 400 * DefaultStyle.dp
							textColor: DefaultStyle.main2_500main
							contentImageColor: modelData.core.starred ? DefaultStyle.danger_500main : DefaultStyle.main2_600
							onClicked: {
								modelData.core.lSetStarred(!modelData.core.starred)
								friendPopup.close()
							}
						}
						Button {
							text: qsTr("Partager")
							background: Item{}
							icon.source: AppIcons.shareNetwork
							icon.width: 24 * DefaultStyle.dp
							icon.height: 24 * DefaultStyle.dp
							spacing: 10 * DefaultStyle.dp
							textSize: 14 * DefaultStyle.dp
							textWeight: 400 * DefaultStyle.dp
							textColor: DefaultStyle.main2_500main
							onClicked: {
								var vcard = modelData.core.getVCard()
								var username = modelData.core.givenName + modelData.core.familyName
								var filepath = UtilsCpp.createVCardFile(username, vcard)
								if (filepath == "") UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La création du fichier vcard a échoué"), false)
								else mainWindow.showInformationPopup(qsTr("VCard créée"), qsTr("VCard du contact enregistrée dans %1").arg(filepath))
								UtilsCpp.shareByEmail(qsTr("Partage de contact"), vcard, filepath)
							}
						}
						Button {
							text: qsTr("Supprimer")
							background: Item{}
							icon.source: AppIcons.trashCan
							icon.width: 24 * DefaultStyle.dp
							icon.height: 24 * DefaultStyle.dp
							spacing: 10 * DefaultStyle.dp
							textSize: 14 * DefaultStyle.dp
							textWeight: 400 * DefaultStyle.dp
							textColor: DefaultStyle.danger_500main
							contentImageColor: DefaultStyle.danger_500main
							visible: !modelData.core.readOnly
							onClicked: {
								mainItem.contactDeletionRequested(modelData)
								friendPopup.close()
							}
						}
					}
				}
			}
		}
		
		MouseArea {
			id: contactArea
			enabled: mainItem.selectionEnabled
			hoverEnabled: mainItem.hoverEnabled
			anchors.fill: contactDelegate
			height: mainItem.height
			acceptedButtons: Qt.AllButtons
			z: -1
			focus: !actionButtons.visible
			Rectangle {
				anchors.fill: contactArea
				opacity: 0.7
				radius: 8 * DefaultStyle.dp
				color: mainItem.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
				visible: contactArea.containsMouse || friendPopup.hovered || mainItem.currentIndex === index
			}
			Keys.onPressed: (event)=> {
				if (event.key == Qt.Key_Space || event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
					contactArea.clicked(undefined)
					event.accepted = true;
				}
			}
			onClicked: (mouse) => {
				if (mouse && mouse.button == Qt.RightButton) {
					friendPopup.open()
				} else {
					mainItem.forceActiveFocus()
					mainItem.currentIndex = index
					if (mainItem.multiSelectionEnabled) {
						var indexInSelection = mainItem.selectedContacts.indexOf(modelData.core.defaultAddress)
						if (indexInSelection == -1) {
							mainItem.addContactToSelection(modelData.core.defaultAddress)
						}
						else {
							mainItem.removeContactFromSelection(indexInSelection, 1)
						}
					}
					mainItem.contactClicked(modelData)
				}
			}
		}
	}
}
