//
//  QRCodeScanView.swift
//  PaiAi
//
//  Created by mac on 16/7/21.
//  Copyright © 2016年 FFIB. All rights reserved.
//

import UIKit
import AVFoundation
import CoreImage

@IBDesignable public class QRCodeScanView: UIView {
    var qrmaskView: QRCodeMaskView?
    var qrscanner: QRCodeScanner?
    var indicatorView: UIActivityIndicatorView = {
        let indicator = UIActivityIndicatorView(style: .white)
        indicator.frame = CGRect(x: (UIScreen.main.bounds.width - 100) / 2 ,
                                 y: (UIScreen.main.bounds.height - 100) / 2,
                                 width: 100,
                                 height: 100)
        return indicator
    }()
    public var configuration = QRCodeConfiguration() {
        didSet {
            qrmaskView?.configuration = configuration
        }
    }
    public weak var delegate: QRCodeScanViewDelegate?
    let picker = UIImagePickerController()
    override public func layoutSubviews() {
        super.layoutSubviews()
        commonInit()
    }

    fileprivate func commonInit() {
        addSubview(indicatorView)
        indicatorView.startAnimating()
        setQRScanner()
        setMaskView()
        start()
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(start),
                                               name: Notification.QRNotification.RestartNotification,
                                               object: nil)
    }

    fileprivate func setMaskView() {
        backgroundColor = UIColor.black
        qrmaskView = QRCodeMaskView(frame: CGRect(x: 0,
                                                  y: 0,
                                                  width: bounds.width,
                                                  height: bounds.height))
        guard let view = qrmaskView else { return }
        view.configuration = configuration
        view.backgroundColor = UIColor(r: 0, g: 0, b: 0, a: 0.2)
        addSubview(view)
    }

    fileprivate func setQRScanner() {
        qrscanner =  QRCodeScanner(scanRect: bounds)
        guard let qrscanner = qrscanner else { return }
        qrscanner.didDecodeCode = {[weak self] res in
            if let weakself = self {
                weakself.delegate?.scanView(weakself,
                                            receivedScanResult: res)
                weakself.qrmaskView?.stopAnimation()
                weakself.indicatorView.stopAnimating()
            }

        }
        qrscanner.didDecodeFail = {[weak self] error in
            if let weakself = self {
                weakself.delegate?.scanView(weakself,
                                            didFinshWithError: error)
                weakself.indicatorView.stopAnimating()
            }
        }
        guard let previewLayer = qrscanner.previewLayer else { return }
        previewLayer.frame = bounds
        layer.insertSublayer(previewLayer, at: 0)
    }

    @objc func start() {
        let queue = DispatchQueue(label: "ffib.startScan.com")
        queue.async {
            self.qrscanner?.startScan()
            DispatchQueue.main.async {
                self.qrmaskView?.startAnimation()
                self.indicatorView.stopAnimating()
            }
        }
    }

    public func openLight() {
        guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
        do {
            try device.lockForConfiguration()
            if device.hasTorch && device.isTorchAvailable {
                if device.isTorchActive {
                    device.torchMode = .off
                } else {
                    device.torchMode = .on
                }
            }
        } catch {
            print("open light error")
        }
    }

    public func openPhotoLibrary(ctl: UIViewController) {
        indicatorView.startAnimating()
        let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
        if status == .notDetermined || status == .authorized {
            picker.sourceType = .photoLibrary
            picker.delegate = self
            ctl.present(picker, animated: true, completion: nil)
        } else {
            let alert = UIAlertController(title: "拒绝访问", message: "请在设置-隐私-相机中允许访问相册", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
            ctl.present(alert, animated: true, completion: nil)
        }
    }
}

extension QRCodeScanView: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) {
            guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
            if let res = image.decodeQRCodeInImage() {
                self.qrscanner?.stopScan()
                self.qrmaskView?.stopAnimation()
                self.delegate?.scanView(self,
                                        receivedScanResult: QRCodeScanResult(metadataType: AVMetadataObject.ObjectType.qr.rawValue,
                                                                             result: res))
            } else {
                let error = NSError(domain: "decode qr code error",
                                    code: 101,
                                    userInfo: nil)
                self.delegate?.scanView(self,
                                        didFinshWithError: error)
            }
            self.indicatorView.stopAnimating()
        }
    }
    
    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
}

//qr code identify the pictures
extension UIImage {

    /// 识别图片内的二维码
    ///
    /// - Returns: 二维码信息
    public func decodeQRCodeInImage() -> String? {
        guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil),
            let cgImage1 = self.cgImage else { return nil }
        let result = detector.features(in: CIImage(cgImage: cgImage1), options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
        guard let first = (result as? [CIQRCodeFeature])?.first else { return nil }
        return first.messageString
    }
}