/*
* 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 CoreFoundation

#if !swift(>=4.2)
// Swift 3/4 compatibility
fileprivate extension RunLoopMode {
  static let `default` = defaultRunLoopMode
}
#endif

#if os(Linux)
public class TSSLSocketTransport {
  init(hostname: String, port: UInt16) {
    // FIXME!
    assert(false, "Security not available in Linux, TSSLSocketTransport Unavilable for now")
  }
}
#else
let isLittleEndian = Int(OSHostByteOrder()) == OSLittleEndian
let htons  = isLittleEndian ? _OSSwapInt16 : { $0 }
let htonl  = isLittleEndian ? _OSSwapInt32 : { $0 }

public class TSSLSocketTransport: TStreamTransport {
  var sslHostname: String
  var sd: Int32 = 0
  
  public init(hostname: String, port: UInt16) throws {
    sslHostname = hostname
    var readStream: Unmanaged<CFReadStream>?
    var writeStream: Unmanaged<CFWriteStream>?
    
    /* create a socket structure */
    var pin: sockaddr_in = sockaddr_in()
    var hp: UnsafeMutablePointer<hostent>? = nil
    for i in 0..<10 {
      
      hp = gethostbyname(hostname.cString(using: String.Encoding.utf8)!)
      if hp == nil {
        print("failed to resolve hostname \(hostname)")
        herror("resolv")
        if i == 9 {
          super.init(inputStream: nil, outputStream: nil) // have to init before throwing
          throw TSSLSocketTransportError(error: .hostanameResolution(hostname: hostname))
        }
        Thread.sleep(forTimeInterval: 0.2)
      } else {
        break
      }
    }
    pin.sin_family  = UInt8(AF_INET)
    pin.sin_addr    = in_addr(s_addr: UInt32((hp?.pointee.h_addr_list.pointee?.pointee)!)) // Is there a better way to get this???
    pin.sin_port    = htons(port)
    
    /* create the socket */
    sd = socket(Int32(AF_INET), Int32(SOCK_STREAM), Int32(IPPROTO_TCP))
    if sd == -1 {
      super.init(inputStream: nil, outputStream: nil) // have to init before throwing
      throw TSSLSocketTransportError(error: .socketCreate(port: Int(port)))
    }
    
    /* open a connection */
    // need a non-self ref to sd, otherwise the j complains
    let sd_local = sd
    let connectResult = withUnsafePointer(to: &pin) {
      connect(sd_local, UnsafePointer<sockaddr>(OpaquePointer($0)), socklen_t(MemoryLayout<sockaddr_in>.size))
    }
    if connectResult == -1 {
      super.init(inputStream: nil, outputStream: nil) // have to init before throwing
      throw TSSLSocketTransportError(error: .connect)
    }
    
    CFStreamCreatePairWithSocket(kCFAllocatorDefault, sd, &readStream, &writeStream)
    
    CFReadStreamSetProperty(readStream?.takeRetainedValue(), .socketNativeHandle, kCFBooleanTrue)
    CFWriteStreamSetProperty(writeStream?.takeRetainedValue(), .socketNativeHandle, kCFBooleanTrue)
    
    var inputStream: InputStream? = nil
    var outputStream: OutputStream? = nil
    if readStream != nil && writeStream != nil {
      
      CFReadStreamSetProperty(readStream?.takeRetainedValue(),
                              .socketSecurityLevel,
                              kCFStreamSocketSecurityLevelTLSv1)
      
      let settings: [String: Bool] = [kCFStreamSSLValidatesCertificateChain as String: true]
      
      CFReadStreamSetProperty(readStream?.takeRetainedValue(),
                              .SSLSettings,
                              settings as CFTypeRef)
      
      CFWriteStreamSetProperty(writeStream?.takeRetainedValue(),
                              .SSLSettings,
                              settings as CFTypeRef)
      
      inputStream = readStream!.takeRetainedValue()
      inputStream?.schedule(in: .current, forMode: .default)
      inputStream?.open()
      
      outputStream = writeStream!.takeRetainedValue()
      outputStream?.schedule(in: .current, forMode: .default)
      outputStream?.open()
      
      readStream?.release()
      writeStream?.release()
    }
    
    
    super.init(inputStream: inputStream, outputStream: outputStream)
    self.input?.delegate = self
    self.output?.delegate = self
  }
  
  func recoverFromTrustFailure(_ myTrust: SecTrust, lastTrustResult: SecTrustResultType) -> Bool {
    let trustTime = SecTrustGetVerifyTime(myTrust)
    let currentTime = CFAbsoluteTimeGetCurrent()
    
    let timeIncrement = 31536000 // from TSSLSocketTransport.m
    let newTime = currentTime - Double(timeIncrement)
    
    if trustTime - newTime != 0 {
      let newDate = CFDateCreate(nil, newTime)
      SecTrustSetVerifyDate(myTrust, newDate!)
      
      var tr = lastTrustResult
      let success = withUnsafeMutablePointer(to: &tr) { trPtr -> Bool in
        if SecTrustEvaluate(myTrust, trPtr) != errSecSuccess {
          return false
        }
        return true
      }
      if !success { return false }
    }
    if lastTrustResult == .proceed || lastTrustResult == .unspecified {
        return false
    }

    print("TSSLSocketTransport: Unable to recover certificate trust failure")
    return true
  }
  
  public func isOpen() -> Bool {
    return sd > 0
  }
}

extension TSSLSocketTransport: StreamDelegate {
  public func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
    
    switch eventCode {
    case Stream.Event(): break
    case Stream.Event.hasBytesAvailable: break
    case Stream.Event.openCompleted: break
    case Stream.Event.hasSpaceAvailable:
      var proceed = false
      var trustResult: SecTrustResultType = .invalid

      var newPolicies: CFMutableArray?
      
      repeat {
        let trust: SecTrust = aStream.property(forKey: .SSLPeerTrust) as! SecTrust
        
        // Add new policy to current list of policies
        let policy = SecPolicyCreateSSL(false, sslHostname as CFString?)
        var ppolicy = policy // mutable for pointer
        let policies: UnsafeMutablePointer<CFArray?>? = nil
        if SecTrustCopyPolicies(trust, policies!) != errSecSuccess {
          break
        }
        withUnsafeMutablePointer(to: &ppolicy) { ptr in
          newPolicies = CFArrayCreateMutableCopy(nil, 0, policies?.pointee)
          CFArrayAppendValue(newPolicies, ptr)
        }
        
        // update trust policies
        if SecTrustSetPolicies(trust, newPolicies!) != errSecSuccess {
          break
        }
        
        // Evaluate the trust chain
        let success = withUnsafeMutablePointer(to: &trustResult) { trustPtr -> Bool in
          if SecTrustEvaluate(trust, trustPtr) != errSecSuccess {
            return false
          }
          return true
        }
        
        if !success {
          break
        }
        
        
        switch trustResult {
        case .proceed:      proceed = true
        case .unspecified:  proceed = true
        case .recoverableTrustFailure:
          proceed = self.recoverFromTrustFailure(trust, lastTrustResult: trustResult)
          
        case .deny:         break
        case .fatalTrustFailure: break
        case .otherError:   break
        case .invalid:      break
        default: break
        }
      } while false
  
      if !proceed {
        print("TSSLSocketTransport: Cannot trust certificate.  Result: \(trustResult)")
        aStream.close()
      }
      
    case Stream.Event.errorOccurred: break
    case Stream.Event.endEncountered: break
    default: break
    }
  }
}
#endif
