//
//  ViewController.swift
//  Monte Carlo Integration
//
//  Created by Jeff Terry on 2/1/17.
//  Copyright © 2017 Jeff Terry. All rights reserved.
//

import Cocoa

var pi = 0.0
var totalGuesses = 0.0
var totalIntegral = 0.0
let radius = 1.0

class ViewController: NSViewController {

    @IBOutlet weak var displayPI: NSTextField!
    @IBOutlet weak var displayGuesses: NSTextField!
    @IBOutlet weak var displayTotalGuesses: NSTextField!
    @IBOutlet weak var displayView: DrawingView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        displayPI.doubleValue = pi
        displayTotalGuesses.doubleValue = totalGuesses

        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }


    /// clear the Display
    ///
    /// - Clears the Display and Resets Parameters
    /// - Parameter sender: Any
    @IBAction func clearDisplay(_ sender: Any) {
        
        
        displayView.shouldIClear = true
        displayView.allThePoints.removeAll()
        displayView.tellGuiToDisplay()
        totalGuesses = 0.0
        pi = 0.0
        totalIntegral = 0.0
        
        displayPI.doubleValue = pi
        displayTotalGuesses.doubleValue = totalGuesses
        
    }
    
    
    /// calculate the value of π
    ///
    /// - Calculates the Value of π using Monte Carlo Integration
    ///
    /// - Parameter sender: Any
    @IBAction func CalculatePI(_ sender: Any) {
        
        
        var maxGuesses = 0.0
        let boundingBoxCalculator = BoundingBox() ///Instantiates Class needed to calculate the area of the bounding box.
        
        
        maxGuesses = displayGuesses.doubleValue
        
        totalIntegral = totalIntegral + calculateMonteCarloIntegral(radius: radius, maxGuesses: maxGuesses)
        
        totalGuesses = totalGuesses + maxGuesses
        
        displayTotalGuesses.doubleValue = totalGuesses
        
        ///Calculates the value of π from the area of a unit circle
        
        pi = totalIntegral/totalGuesses * boundingBoxCalculator.calculateSurfaceArea(numberOfSides: 2, lengthOfSide1: 2.0*radius, lengthOfSide2: 2.0*radius, lengthOfSide3: 0.0)
        
        displayPI.doubleValue = pi
        
        displayView.tellGuiToDisplay()
        
        
    }
    
    /// calculates the Monte Carlo Integral of a Circle
    ///
    /// - Parameters:
    ///   - radius: radius of circle
    ///   - maxGuesses: number of guesses to use in the calculaton
    /// - Returns: ratio of points inside to total guesses. Must mulitply by area of box in calling function
    func calculateMonteCarloIntegral(radius: Double, maxGuesses: Double) -> Double {
        
        var numberOfGuesses = 0.0
        var pointsInRadius = 0.0
        var integral = 0.0
        var point = (xPoint: 0.0, yPoint: 0.0, radiusPoint: 0.0, color: "Red")
        
        
        while numberOfGuesses < maxGuesses {
            
            /* Calculate 2 random values within the box */
            /* Determine the distance from that point to the origin */
            /* If the distance is less than the unit radius count the point being within the Unit Circle */
            point.xPoint = Double.getRandomNumber(lower: -radius, upper: radius)
            point.yPoint = Double.getRandomNumber(lower: -radius, upper: radius)
            point.radiusPoint = sqrt(pow(point.xPoint,2.0) + pow(point.yPoint,2.0))
            
            displayView.shouldIDrawPoints = true 
            
            // if inside the circle add to the number of points in the radius
            if((radius - point.radiusPoint) >= 0.0){
                pointsInRadius += 1.0
                
                point.xPoint = point.xPoint * Double(displayView.frame.width)/2.0 + Double(displayView.frame.width)/2.0
                point.yPoint = point.yPoint * Double(displayView.frame.height)/2.0 + Double(displayView.frame.height)/2.0
                point.color = "Red"
                displayView.addPoint(xPointa:point.xPoint, yPointb: point.yPoint, radiusPointc: point.radiusPoint, colord: point.color)
                
            }
            else { //if outside the circle do not add to the number of points in the radius
                
                point.xPoint = point.xPoint * Double(displayView.frame.width)/2.0 + Double(displayView.frame.width)/2.0
                point.yPoint = point.yPoint * Double(displayView.frame.height)/2.0 + Double(displayView.frame.height)/2.0
                point.color = "Blue"
                displayView.addPoint(xPointa:point.xPoint, yPointb: point.yPoint, radiusPointc: point.radiusPoint, colord: point.color)
                

                
            }
            
            numberOfGuesses += 1.0
            
            
            
            
            }
    
        
        integral = Double(pointsInRadius)
        
        
        return integral
        }

}

