//Licensed to the Apache Software Foundation (ASF) under one
//or more contributor license agreements.  See the NOTICE file
//distributed with this work for additional information
//    regarding copyright ownership.  The ASF licenses this file
//to you 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 Foundation
import XCTest
import Swifter

extension AlertController: Routeable {
    
    var name: String {
        return "alert"
    }
    
    func handleRoutes(_ request: HttpRequest) -> HttpResponse {
        guard let bodyString = String(bytes: request.body, encoding: .utf8) else {
            return .internalServerError
        }
        
        var bodyParameters: [String] = bodyString.components(separatedBy: "\n")
        bodyParameters.removeFirst()
        let actionValue = bodyParameters.removeFirst()
        
        guard let action = AlertAction(rawValue: actionValue) else {
            return .internalServerError
        }
        
        switch action {
        case .tap:      return tapHandler(bodyParameters)
        case .input:    return inputHandler(bodyParameters)
        }
    }
    
}

final class AlertController {
    
    enum AlertAction: String {
        case tap
        case input
    }
    
    private func tapHandler(_ parameters: [String]) -> HttpResponse {        
        let alert:XCUIElement
        let systemApp = XCUIApplication(bundleIdentifier: "com.apple.springboard")
        if systemApp.alerts.count > 0 {
            alert = systemApp.alerts.firstMatch
        } else if application.alerts.count > 0 {
            alert = application.alerts.firstMatch
        } else {
            return Output(message: "no alert found", status: "-99").toHttpResponse()
        }
        
        guard var index = Int(parameters[0]) else {
            return Output(message: "missing or bad parameters", status: "-99").toHttpResponse()
        }
        
        if (index == 0) {
            index = 1
        }
        
        guard index <= alert.buttons.count else {
            return Output(message: "index not found", status: "-99").toHttpResponse()
        }
        
        alert.buttons.element(boundBy: Int(index - 1)).tap()
        
        return Output(message: "tap on element").toHttpResponse()
    }
    
    private func inputHandler(_ parameters: [String]) -> HttpResponse {
        guard application.state == .runningForeground else {
            return Output(message: "tap on element").toHttpResponse()
        }
                
        let text: String = parameters[1]
        let coordinates = parameters[0].components(separatedBy: ";")
                
        if (application.alerts.allElementsBoundByIndex.count > 0) {
            let alert = application.alerts.firstMatch
            let point = CGPoint(x: Double(coordinates[0])! / Double(ATSDevice.current.deviceScale), y: Double(coordinates[1])! / Double(ATSDevice.current.deviceScale))
            if let inputField = alert.textFields.allElementsBoundByIndex.first(where: { $0.frame.contains(point) }) {
                inputField.tap()
                inputField.typeText(text)
                return Output(message: "text on element").toHttpResponse()
            }
        }
        
        return Output(message: "textField does not exist").toHttpResponse()
    }
}
