/*
 * Copyright (c) 2024 Ross Cunniff
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
/* Significant portions of this code were adapted from Hoverware, whose
 * GPL copyright is: */
/* (c) Copyright Hewlett-Packard Company 2001
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
using namespace oadl;

#include "libo3d.oah"
#include "libstd.oah"

o3d::Display disp(nil,nil) { o3dDefaultOptFlags = o3d::OPT_USE_DL }
var done = 0;

proc callback(draw, event)
{
    switch( event ) {
    case o3d::INPUT_KEYBOARD :
        if( arg(2) == 27 ) {
            done = 1;
        }
    case o3d::INPUT_DESTROY :
        done = 1;
    case o3d::INPUT_CONFIG :
        disp.viewport(0, 0, arg(4), arg(5));
    }
}

proc main(args)
{
    var
        n,
        draw,
        env, sphere, light, cam, tm,
        CamAng = 0.0,
        cy, cz,
        Mat,
        Ang = 0.0,
        graphN = 133, graphM = 165, i, wireframe = false, sampvert = false;

    n = args.length();
    for( i = 1; i < n; i++ ) {
        switch( args[i] ) {
        case "-wire" :
            wireframe = true;
        case "-rows" :
            if( i < (n-1) ) {
                i++;
                graphN = str2var(args[i]);
            }
        case "-cols" :
            if( i < (n-1) ) {
                i++;
                graphM = str2var(args[i]);
            }
        case "-rgb" :
            sampvert = true;
        }
    }

    disp.chooseVisual(o3d::VIS_DBUFF|o3d::VIS_DEPTH, 0);
    draw = disp.createWindow( "Test", 100, 100, 512, 512, o3d::WIN_INPUT );
    disp.makeCurrent(draw);
    disp.inputHandler(callback);

    env = new o3d::Environ() {
        AmbientFactor = 0.5
        BackgroundColor = [0.0, 0.0, 1.0]
        FogColor = [0.0, 0.0, 1.0]
        Fog = true
        FogPlanes = [1.0, 3.5]
        FogType = o3d::FOG_LINEAR
    };

    cam = new o3d::Camera() {
        Planes = [0.5, 3.5]
        Field = 90
        Perspective = true
    };

    tm = new o3d::Texture() {
        FileName = "Texture/Earth.jpg"
        Scale = [1.0, 0.75, 1.0]
        Pos = [0.0, 0.25, 0.0]
    };

    sphere = new o3d::Sphere() {
        Texture = tm
        Color = [1.0, 0.8, 0.4]
        OptFlags = o3d::OPT_DL_ATTRS
        HasNormals = true
        TwoSided = true
        GraphN = graphN
        GraphM = graphM
        Wireframe = wireframe
        SampVert = sampvert
        LatRange = [-45, 90]
        Shininess = 0.1
    };

    light = new o3d::Light() {
        Dir = [1.0, 1.0, -1.0]
    };


    Mat = new PackFloat(16);
    while( !done ) {
        env.draw(disp);

        cy = math::cos(CamAng * math::PI / 180.0);
        cz = math::sin(CamAng * math::PI / 180.0);
        with (cam) {
            Pos = [0.0, 2.0*cy, 2.0*cz]
            Dir = [0.0, -cy, -cz]
            Up = [0.0, -cz, cy]
        }

        cam.draw();
        light.draw();
        o3d::RotateY( Mat, Ang );
        disp.pushMatrix(Mat);
        sphere.draw();
        disp.popMatrix();
        disp.update( o3d::UPDATE_ALL );
        Ang += 5.0;
        if( Ang > 360.0 ) Ang -= 360.0;
        CamAng += 4.0;
        if( CamAng > 360.0 ) CamAng -= 360.0;
    }
}