//
//  AudioPlotter.swift
//  ToneShaperPreview
//
//  Created by Joseph Pagliaro on 12/7/23.
//

import Foundation

class AudioPlotter {
    
    let sampleCount = 44100
    let bufferSize = 526  
    
    var allSampleIFValues:[Double] = []
    var integral:[Double] = []
    
    var useSimpsons: Bool
    
    init(useSimpsons: Bool) {
        
        self.useSimpsons = useSimpsons
        
            // equally spaced 
        let N:Double = 6
        let DF:Double = N/6
        let x:[Double] = [0 * DF, 1 * DF, 2 * DF, 3 * DF, 4 * DF, 5 * DF, 6 * DF] 
        let y:[Double] = [30,440,50,440,50,440,50]
        
        let userIFCurve:[CGPoint] = [CGPoint(x: x[0], y: y[0]), CGPoint(x: x[1], y: y[1]), CGPoint(x: x[2], y: y[2]), CGPoint(x: x[3], y: y[3]), CGPoint(x: x[4], y: y[4]), CGPoint(x: x[5], y: y[5]), CGPoint(x: x[6], y: y[6])]
        
        
            // scale up
        let scale = PiecewiseIntegrator.scale(sampleCount: sampleCount, userIFCurve: userIFCurve)
        let userIFValues = PiecewiseIntegrator.userIFValues_by_interpolateUserIFCurve(userIFCurve: userIFCurve)
        
        let partition = PiecewiseIntegrator.createPartitionRanges(sampleCount: sampleCount, rangeCount: bufferSize)  
        
            // compute allSampleIFValues - all samples values by partitioning
        for sampleRange in partition {
            let sampleIFValuesForRange = PiecewiseIntegrator.sampleIFValuesForRange(scale: scale, sampleRange: sampleRange, userIFValues: userIFValues)
            allSampleIFValues.append(contentsOf: sampleIFValuesForRange)
        }
        
        let stepSize = 1.0 / Double(sampleCount)
        
        let piecewise_integrator = PiecewiseIntegrator(userIFCurve: userIFCurve, sampleCount: sampleCount, rangeCount: bufferSize, delta: stepSize, useSimpsons: useSimpsons)
        
        while let piecewiseIntegral = piecewise_integrator.nextIntegral() {
            integral = integral + piecewiseIntegral
        }
    }
    
    
    func indexForTime(_ t:Double) -> Int {
        let stepSize = 1/Double(sampleCount)
        return Int((t / stepSize).rounded(.down))
    }
    
    func instantaneous_frequency(_ t:CGFloat) -> CGFloat? {
        
        if indexForTime(t) >= 0 && indexForTime(t) < allSampleIFValues.count {
            return allSampleIFValues[indexForTime(t)]
        }
        return nil
    }
    
    func audio_samples(_ t:CGFloat) -> CGFloat? { 
        if indexForTime(t) >= 0 && indexForTime(t) < integral.count {
            return 10 * sin(2 * .pi * integral[indexForTime(t)])
        }
        return nil
        
    }
}
