#if os(Linux)
import Glibc
#if GLES
    import COpenGLES.gles2
    #else
    import COpenGL
#endif
#else
#if GLES
    import OpenGLES
    #else
    import OpenGL.GL3
#endif
#endif

public enum FillMode {
    case stretch
    case preserveAspectRatio
    case preserveAspectRatioAndFill
    
    func transformVertices(_ vertices: [GLfloat], fromInputSize: GLSize, toFitSize: GLSize) -> [GLfloat] {
        guard vertices.count == 8 else { fatalError("Attempted to transform a non-quad to account for fill mode.") }
        
        let aspectRatio = GLfloat(fromInputSize.height) / GLfloat(fromInputSize.width)
        let targetAspectRatio = GLfloat(toFitSize.height) / GLfloat(toFitSize.width)
        
        let yRatio: GLfloat
        let xRatio: GLfloat
        switch self {
            case .stretch: return vertices
            case .preserveAspectRatio:
                if aspectRatio > targetAspectRatio {
                    yRatio = 1.0
//                    xRatio = (GLfloat(toFitSize.height) / GLfloat(fromInputSize.height)) * (GLfloat(fromInputSize.width) / GLfloat(toFitSize.width))
                    xRatio = (GLfloat(fromInputSize.width) / GLfloat(toFitSize.width)) * (GLfloat(toFitSize.height) / GLfloat(fromInputSize.height))
                } else {
                    xRatio = 1.0
                    yRatio = (GLfloat(fromInputSize.height) / GLfloat(toFitSize.height)) * (GLfloat(toFitSize.width) / GLfloat(fromInputSize.width))
                }
            case .preserveAspectRatioAndFill:
                if aspectRatio > targetAspectRatio {
                    xRatio = 1.0
                    yRatio = (GLfloat(fromInputSize.height) / GLfloat(toFitSize.height)) * (GLfloat(toFitSize.width) / GLfloat(fromInputSize.width))
                } else {
                    yRatio = 1.0
                    xRatio = (GLfloat(toFitSize.height) / GLfloat(fromInputSize.height)) * (GLfloat(fromInputSize.width) / GLfloat(toFitSize.width))
            }
        }
        // Pixel-align to output dimensions
//        return [vertices[0] * xRatio, vertices[1] * yRatio, vertices[2] * xRatio, vertices[3] * yRatio, vertices[4] * xRatio, vertices[5] * yRatio, vertices[6] * xRatio, vertices[7] * yRatio]
        // TODO: Determine if this is misaligning things
        
		let xConversionRatio: GLfloat = xRatio * GLfloat(toFitSize.width) / 2.0
		let xConversionDivisor = GLfloat(toFitSize.width) / 2.0
		let yConversionRatio: GLfloat = yRatio * GLfloat(toFitSize.height) / 2.0
		let yConversionDivisor = GLfloat(toFitSize.height) / 2.0

		// The Double casting here is required by Linux

        let value1 = GLfloat(round(Double(vertices[0] * xConversionRatio))) / xConversionDivisor
        let value2 = GLfloat(round(Double(vertices[1] * yConversionRatio))) / yConversionDivisor
        let value3 = GLfloat(round(Double(vertices[2] * xConversionRatio))) / xConversionDivisor
        let value4 = GLfloat(round(Double(vertices[3] * yConversionRatio))) / yConversionDivisor
        let value5 = GLfloat(round(Double(vertices[4] * xConversionRatio))) / xConversionDivisor
        let value6 = GLfloat(round(Double(vertices[5] * yConversionRatio))) / yConversionDivisor
        let value7 = GLfloat(round(Double(vertices[6] * xConversionRatio))) / xConversionDivisor
        let value8 = GLfloat(round(Double(vertices[7] * yConversionRatio))) / yConversionDivisor

        return [value1, value2, value3, value4, value5, value6, value7, value8]

        // This expression chokes the compiler in Xcode 8.0, Swift 3
//        return [GLfloat(round(Double(vertices[0] * xConversionRatio))) / xConversionDivisor, GLfloat(round(Double(vertices[1] * yConversionRatio))) / yConversionDivisor,
//                GLfloat(round(Double(vertices[2] * xConversionRatio))) / xConversionDivisor, GLfloat(round(Double(vertices[3] * yConversionRatio))) / yConversionDivisor,
//                GLfloat(round(Double(vertices[4] * xConversionRatio))) / xConversionDivisor, GLfloat(round(Double(vertices[5] * yConversionRatio))) / yConversionDivisor,
//                GLfloat(round(Double(vertices[6] * xConversionRatio))) / xConversionDivisor, GLfloat(round(Double(vertices[7] * yConversionRatio))) / yConversionDivisor]
    }
}
