//
//  Photo.swift
//  MCPlus
//
//  Created by seo ha on 07/02/2019.
//  Copyright © 2019 KangSH. All rights reserved.
//

import Foundation

class Photo: CustomStringConvertible, Codable {
    var user:User?
    var file:String?
    var date:String?
    var key:String?
    var isSended:Bool = false
}

extension Photo{
    
    func create(){
        let contactDB = SqlClient.shared.DB
        // 데이터베이스를 열고 contacts 테이블을 생성한다.
        if contactDB.open() {
            let sql_stmt = "CREATE TABLE IF NOT EXISTS Photo (ID INTEGER PRIMARY KEY AUTOINCREMENT, userId TEXT, userName TEXT, userAge TEXT, userGender TEXT, fileName TEXT, fileDate TEXT, fileKey TEXT, user TEXT, fileSend INTEGER NOT NULL DEFAULT 0)"
            if !contactDB.executeStatements(sql_stmt) {
                print("Error \(contactDB.lastErrorMessage())")
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }
    }
    
    func isSave() -> Bool {
        guard let id = self.user?.patientId, let key = self.key, let file = self.file else {
            return false
        }
        let contactDB = SqlClient.shared.DB
        
        if contactDB.open() {
            let querySQL = "SELECT ID FROM Photo where userId='\(id)' and fileKey='\(key)' and fileName='\(file)' "
            
            let result: FMResultSet? = contactDB.executeQuery(querySQL, withArgumentsIn: [])
            // next 메서드는 일치하는 레코드가 적어도 하나 이상인지 확인하기 위함
            if result?.next() == true{
                return true
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }
        
        return false
    }
    
    func save(){
        self.create()
        
        if self.isSave(){
            self.update()
            
        }else{
            let contactDB = SqlClient.shared.DB
            
            guard let id = self.user?.patientId, let name = self.user?.patientNm, let age = self.user?.age, let gender = self.user?.gender,
                let file = self.file, let date = self.date, let key = self.key, let user = self.user else{
                    return
            }
            guard let data = try? JSONEncoder().encode(user) else{ return }
            guard let userString = String(data: data, encoding: .utf8) else{ return }
            
            if contactDB.open() {
                let insertSQL = "INSERT INTO Photo (userId, userName, userAge, userGender, fileName, fileDate, fileKey, user, fileSend) VALUES ('\(id)', '\(name)', '\(age)', '\(gender)', '\(file)', '\(date)', '\(key)', '\(userString)', '\(self.isSended ? 1 : 0)') "
                
                let result = contactDB.executeUpdate(insertSQL, withArgumentsIn: [])
                
                if !result {
                    print("Error \(contactDB.lastErrorMessage())")
                }
                contactDB.close()
            } else {
                print("Error \(contactDB.lastErrorMessage())")
            }
        }
    }
    
    func update(){
        self.create()
        let contactDB = SqlClient.shared.DB
        
        guard let id = self.user?.patientId, let name = self.user?.patientNm, let age = self.user?.age, let gender = self.user?.gender,
            let file = self.file, let date = self.date, let key = self.key else{
                return
        }
        if contactDB.open() {
            let insertSQL = "UPDATE Photo SET userName='\(name)', userAge='\(age)', userGender='\(gender)', fileDate='\(date)', fileSend='\(self.isSended ? 1 : 0)' where userId='\(id)' and fileKey='\(key)' and fileName='\(file)'"
            
            let result = contactDB.executeUpdate(insertSQL, withArgumentsIn: [])
            
            if !result {
                print("Error \(contactDB.lastErrorMessage())")
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }
        
    }
    
    func recovery() -> Bool {

        let contactDB = SqlClient.shared.DB
        
        guard let id = self.user?.patientId, let key = self.key, let file = self.file else {
            return false
        }
        
        if contactDB.open() {
            let querySQL = "SELECT user, fileDate, fileSend FROM Photo where userId='\(id)' and fileKey='\(key)' and fileName='\(file)' "

            let result: FMResultSet? = contactDB.executeQuery(querySQL, withArgumentsIn: [])
            // next 메서드는 일치하는 레코드가 적어도 하나 이상인지 확인하기 위함
            if result?.next() == true{
                guard let userString = result?.string(forColumn: "user") else{ return false}
                guard let userData = userString.data(using: .utf8) else{ return false}
                guard let user = try? JSONDecoder().decode(User.self, from: userData) else{ return false}
                self.user = user
                self.date = result?.string(forColumn: "fileDate")
                
                if let send = result?.int(forColumn: "fileSend"), send == 1{
                    self.isSended = true
                }else{
                    self.isSended = false
                }
                
                
                return true
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }

        return false
    }
    
    func delete() -> Bool {
        let contactDB = SqlClient.shared.DB
        guard let id = self.user?.patientId, let key = self.key, let file = self.file else {
            return false
        }
        
        if contactDB.open() {
            let querySQL = "DELETE FROM Photo where userId='\(id)' and fileKey='\(key)' and fileName='\(file)' "
            
            let result: FMResultSet? = contactDB.executeQuery(querySQL, withArgumentsIn: [])
            // next 메서드는 일치하는 레코드가 적어도 하나 이상인지 확인하기 위함
            if result?.next() == true{
                return true
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }
        
        return false
    }

    static func list(user:User) -> [(String,[Photo])]{
        var returnDic:[(String,[Photo])]
        let contactDB = SqlClient.shared.DB
        returnDic = [(String,[Photo])]()

        guard let id = user.patientId else{
            return returnDic
        }
        if contactDB.open() {
            let querySQL = "SELECT userId, fileName, fileKey FROM Photo where userId='\(id)' ORDER BY fileDate ASC"

            let result: FMResultSet? = contactDB.executeQuery(querySQL, withArgumentsIn: [])
            // next 메서드는 일치하는 레코드가 적어도 하나 이상인지 확인하기 위함
            var photos = [Photo]()
            while result?.next() == true{
                let photo = Photo()
                let _user = User()
                photo.user = _user
                photo.user?.patientId = result?.string(forColumn: "userId")
                photo.file = result?.string(forColumn: "fileName")
                photo.key = result?.string(forColumn: "fileKey")
                if photo.recovery(){
                    if self.filter(photo, user){
                        photos.append(photo)
                    }
                }
            }
            let keys = photos.map({$0.key})
                .compactMap({$0})
            let _keys = Set(keys).sorted().reversed()
            
            for key in _keys{
                print(key)
                returnDic.append((key, photos.filter({$0.key == key})))
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }
        return returnDic
    }
    
    static func allList(user:User) -> [(String,[Photo])]{
        var returnDic:[(String,[Photo])]
        let contactDB = SqlClient.shared.DB
        returnDic = [(String,[Photo])]()
        
        if contactDB.open() {
            let querySQL = "SELECT userId, fileName, fileKey FROM Photo ORDER BY fileDate ASC"
            
            let result: FMResultSet? = contactDB.executeQuery(querySQL, withArgumentsIn: [])
            // next 메서드는 일치하는 레코드가 적어도 하나 이상인지 확인하기 위함
            
            var photos = [Photo]()
            while result?.next() == true{
                
                let photo = Photo()
                let _user = User()
                photo.user = _user
                photo.user?.patientId = result?.string(forColumn: "userId")
                photo.file = result?.string(forColumn: "fileName")
                photo.key = result?.string(forColumn: "fileKey")
                
                if photo.recovery(){
                    if self.filter(photo, user){
                        photos.append(photo)
                    }
                }
            }
            let keys = photos.map({$0.key}).compactMap({$0})
            let _keys = Set(keys).sorted().reversed()
            for key in _keys{
                returnDic.append((key, photos.filter({$0.key == key})))
            }
            contactDB.close()
        } else {
            print("Error \(contactDB.lastErrorMessage())")
        }
        return returnDic
    }
    
    static func filter(_ photo:Photo, _ user:User) -> Bool {
        if photo.user?.userId != user.userId{
            return false
        }
        return true
    }
    
}

