//
//  ThereManager.swift
//  NaADae
//
//  Created by Lee on 2020/06/25.
//  Copyright © 2020 Kira. All rights reserved.
//

import Foundation
import Firebase
import CoreLocation

class ThereManager {
  
  // MARK: - Data Model
  
  typealias ThereModel = GwangClModel
  typealias ThereReference = GwangClReference
  
  struct TargetLocationModel {
    let title: String
    let coordinate: CLLocationCoordinate2D
  }

  private let targetLocations: [TargetLocationModel] = [
    // 국내
    TargetLocationModel(title: "청와대 춘추관 화장실", coordinate: CLLocationCoordinate2D(latitude: 37.586913, longitude: 126.978839)),
    TargetLocationModel(title: "독도", coordinate: CLLocationCoordinate2D(latitude: 37.241535, longitude: 131.865168)),
    TargetLocationModel(title: "추자도 해양파출소", coordinate: CLLocationCoordinate2D(latitude: 33.941208, longitude: 126.324424)),
    TargetLocationModel(title: "애플 가로수길", coordinate: CLLocationCoordinate2D(latitude: 37.520908, longitude: 127.022708)),
    TargetLocationModel(title: "제부도 119 지역대", coordinate: CLLocationCoordinate2D(latitude: 37.163386, longitude: 126.621442)),
    TargetLocationModel(title: "논산 훈련소", coordinate: CLLocationCoordinate2D(latitude: 36.115167, longitude: 127.100040)),
    TargetLocationModel(title: "고종의 길", coordinate: CLLocationCoordinate2D(latitude: 37.567735, longitude: 126.972301)),
    TargetLocationModel(title: "성유리", coordinate: CLLocationCoordinate2D(latitude: 36.631276, longitude: 128.017481)),
    TargetLocationModel(title: "효리", coordinate: CLLocationCoordinate2D(latitude: 36.033122, longitude: 129.012759)),
    TargetLocationModel(title: "업쓰(개발자) 최애 통닭집", coordinate: CLLocationCoordinate2D(latitude: 35.554399, longitude: 129.323525)),
    
    TargetLocationModel(title: "성훈이 아빠가 방구끼려다 바지에 똥지린 곳", coordinate: CLLocationCoordinate2D(latitude: 35.153163, longitude: 129.118637)),
    TargetLocationModel(title: "1000JI 의 집", coordinate: CLLocationCoordinate2D(latitude: 37.448174, longitude: 126.797547)),
    TargetLocationModel(title: "2002년도 마지막 개구리가 죽은 곳", coordinate: CLLocationCoordinate2D(latitude: 36.662687, longitude: 127.864559)),
    TargetLocationModel(title: "단종유배지(청령포)", coordinate: CLLocationCoordinate2D(latitude: 37.177494, longitude: 128.445506)),
    TargetLocationModel(title: "도산서원", coordinate: CLLocationCoordinate2D(latitude: 36.727252, longitude: 128.843511)),
    TargetLocationModel(title: "우기의 뻬이버릿 야경 플레이스", coordinate: CLLocationCoordinate2D(latitude: 37.602687, longitude: 126.982595)),
    TargetLocationModel(title: "무한도전 논두렁 달리기 촬영지", coordinate: CLLocationCoordinate2D(latitude: 37.718573, longitude: 126.358995)),
    TargetLocationModel(title: "무한도전 1회 촬영지", coordinate: CLLocationCoordinate2D(latitude: 37.455909, longitude: 126.368427)),
    TargetLocationModel(title: "서울 소환사의 협곡", coordinate: CLLocationCoordinate2D(latitude: 37.509414, longitude: 127.060850)),
    TargetLocationModel(title: "우항리 공룡화석지", coordinate: CLLocationCoordinate2D(latitude: 34.590666, longitude: 126.435443)),
    
    TargetLocationModel(title: "인천상륙작전 상륙지점", coordinate: CLLocationCoordinate2D(latitude: 37.476546, longitude: 126.597805)),
    TargetLocationModel(title: "창렬로", coordinate: CLLocationCoordinate2D(latitude: 35.199795, longitude: 128.077051)),
    TargetLocationModel(title: "야동리", coordinate: CLLocationCoordinate2D(latitude: 37.111274, longitude: 127.872972)),
    TargetLocationModel(title: "안기세영아파트", coordinate: CLLocationCoordinate2D(latitude: 36.584401, longitude: 128.713798)),
    
    // 국외
    TargetLocationModel(title: "백악관", coordinate: CLLocationCoordinate2D(latitude: 38.898168, longitude: -77.036471)),
    TargetLocationModel(title: "남북공동연락사무소", coordinate: CLLocationCoordinate2D(latitude: 37.933556, longitude: 126.621900)),
    TargetLocationModel(title: "남극세종과학기지", coordinate: CLLocationCoordinate2D(latitude: -62.223275, longitude: -58.787957)),
    TargetLocationModel(title: "상해 대한민국임시정부", coordinate: CLLocationCoordinate2D(latitude: 31.218635, longitude: 121.474760)),
    TargetLocationModel(title: "이준 열사 기념관", coordinate: CLLocationCoordinate2D(latitude: 52.074470, longitude: 4.315776)),
    TargetLocationModel(title: "나이아가라 폭포", coordinate: CLLocationCoordinate2D(latitude: 43.082949, longitude: -79.074141)),
    TargetLocationModel(title: "백두산 매표소", coordinate: CLLocationCoordinate2D(latitude: 41.993312, longitude: 128.077464)),
    TargetLocationModel(title: "애플 본사", coordinate: CLLocationCoordinate2D(latitude: 37.334891, longitude: -122.009003)),
    TargetLocationModel(title: "구글 본사", coordinate: CLLocationCoordinate2D(latitude: 37.422128, longitude: -122.084068)),
    TargetLocationModel(title: "슬램덩크 북산고", coordinate: CLLocationCoordinate2D(latitude: 35.308879, longitude: 139.503892)),
    
    TargetLocationModel(title: "이토히로부미 저격당한 곳", coordinate: CLLocationCoordinate2D(latitude: 45.761737, longitude: 126.633408)),
    TargetLocationModel(title: "타이베이 101", coordinate: CLLocationCoordinate2D(latitude: 25.034112, longitude: 121.564560)),
    TargetLocationModel(title: "에펠탑", coordinate: CLLocationCoordinate2D(latitude: 48.858476, longitude: 2.294481)),
    TargetLocationModel(title: "기자의 대스핑크스", coordinate: CLLocationCoordinate2D(latitude: 29.975492, longitude: 31.138147)),
    TargetLocationModel(title: "자유의 여신상", coordinate: CLLocationCoordinate2D(latitude: 40.689404, longitude: -74.044522)),
    TargetLocationModel(title: "호안끼엠 호", coordinate: CLLocationCoordinate2D(latitude: 21.028785, longitude: 105.852161)),
  ]
  
  

  // MARK: - Property

  private let vmClient: ClientViewModel
  private let gameCollection: CollectionReference
  private var pointDocument: DocumentReference?
  private var listener: ListenerRegistration?

  private let _random: Int
  private var _results = [ThereModel]()



  // MARK: - Init

  init(clientViewModel: ClientViewModel) {
    self.vmClient = clientViewModel
    self.gameCollection = Firestore
      .firestore()
      .collection(FirebaseReference.client.rawValue)
      .document(clientViewModel.clientDocumentID)
      .collection(GameReference.there.rawValue)
    
    self._random = (0..<targetLocations.count).randomElement() ?? 0
  }

  deinit {
    listener?.remove()
  }
  
  
  
  // MARK: - Interface
  
  var randomTarget: TargetLocationModel { targetLocations[_random] }
  var results: [ThereModel] { _results }
  
  
  
  func updatePoint(point: Int, completion: @escaping (Result<String, Error>) -> Void) {
    pointDocument = gameCollection
      .addDocument(data: [
        ThereReference.nickName: vmClient.nickName,
        ThereReference.point: point
      ]) { (error) in
        
        print("\n---------------------- [ ThereManager updatePoint ] ----------------------")
        
        if let error = error {
          completion(.failure(error))
          
        } else {
          completion(.success("Success"))
        }
    }
  }
  
  
  
  func setListener(completion: @escaping (Result<Bool, Error>) -> Void) {
    listener = gameCollection
      .addSnapshotListener { [weak self] (snapshot, error) in
        
        print("\n---------------------- [ ThereManager setListener ] ----------------------")
        
        if let error = error {
          completion(.failure(error))
          
        } else {
          guard let documents = snapshot?.documents else {
            completion(.failure(NSError(domain: "ThereManager setListener", code: 00)))
            return
          }
          
          var tempResults = [ThereModel]()
          for document in documents {
            let data = document.data()
            
            guard
              let nickName = data[ThereReference.nickName] as? String,
              let point = data[ThereReference.point] as? Int
              else {
                completion(.failure(NSError(domain: "ThereManager setListener", code: 01)))
                return
            }
            
            let tempResult = ThereModel(nickName: nickName, point: point)
            tempResults.append(tempResult)
          }
          
          tempResults.sort { $0.point < $1.point }
          self?._results = tempResults
          
          completion(.success(tempResults.count == self?.vmClient.players.count))
        }
    }
  }
  
  
  
  func addPenalizer() {
    guard
      let penalizer = _results.last,
      vmClient.position == .main
      else { return }
    
    let tempPenalizers = _results
      .filter { $0.point == penalizer.point }
      .map { $0.nickName }
    
    vmClient.addPenalizers(penalizers: tempPenalizers)
  }
  
  
  
  func removeListener() {
    listener?.remove()
    listener = nil
  }
  
  
  
  func deleteDocument() {
    pointDocument?.delete()
    pointDocument = nil
  }
}
