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

import SwiftUI

func GeneratePath(a:CGFloat, b:CGFloat, N:Int, frameSize:CGSize, inset:CGFloat = 10.0, graphs: [(_ x:CGFloat) -> CGFloat?]) -> [Path] {
    
    guard frameSize.width > 0, frameSize.height > 0  else {
        return Array(repeating: Path(), count: graphs.count)
    }
    
    var plots:[[CGPoint]] = []
    
    var minimum_y:CGFloat = 0
    var maximum_y:CGFloat = 0
    
    var minimum_x:CGFloat = 0
    var maximum_x:CGFloat = 0
    
    for graph in graphs {
        
        var plot:[CGPoint] = []
        
        for i in 0...N {
            
            let x = a + (CGFloat(i) * ((b - a) / CGFloat(N)))
            if let y = graph(x) {
                if y < minimum_y {
                    minimum_y = y
                }
                if y > maximum_y {
                    maximum_y = y
                }
                
                if x < minimum_x {
                    minimum_x = x
                }
                if x > maximum_x {
                    maximum_x = x
                }
                
                plot.append(CGPoint(x: x, y: y))
            } 
        }
        
        plots.append(plot)
    }
    
    let frameRect = CGRect(x: 0, y: 0, width: frameSize.width, height: frameSize.height)
    let plotRect = frameRect.insetBy(dx: inset, dy: inset)
    
    let x0 = plotRect.origin.x
    let y0 = plotRect.origin.y
    let W = plotRect.width
    let H = plotRect.height
    
    func tx(_ x:CGFloat) -> CGFloat {
        if maximum_x == minimum_x {
            return x0 + W
        }
        return (x0 + W * ((x - minimum_x) / (maximum_x - minimum_x)))
    }
    
    func ty(_ y:CGFloat) -> CGFloat {
        if maximum_y == minimum_y {
            return frameSize.height - (y0 + H)
        }
        return frameSize.height - (y0 + H * ((y - minimum_y) / (maximum_y - minimum_y))) // subtract from frameSize.height to flip coordinates
    }
    
        // map points into plotRect using linear interpolation
    for i in 0...plots.count-1 {
        for j in 0...plots[i].count-1 {
            
            let x = plots[i][j].x
            let y = plots[i][j].y
            
            plots[i][j].x = tx(x)
            plots[i][j].y = ty(y)
        }
    }
    
        // create the paths
    var paths:[Path] = []
    
    for i in 0...plots.count-1 {
        let path = Path { path in
            
            let x = plots[i][0].x
            let y = plots[i][0].y
            
            path.move(to: CGPoint(x: x, y: y))
            
            for j in 1...plots[i].count-1 {
                let x = plots[i][j].x
                let y = plots[i][j].y
                path.addLine(to: CGPoint(x: x, y: y))
            }
        }
        
        paths.append(path)
    }
    
    return paths
}
