//
// Applesoft BASIC Interpreter in Javascript
// Low Resolution Graphics (LoRes) Emulation
//

// Copyright 2009 Joshua Bell
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Usage:
//   
//   var lores = new LoRes( element, width, height )
//   lores.clear()
//   lores.setColor( color_index )
//   lores.plot( x, y )
//   lores.hlin( x1, x2, y )
//   lores.vlin( x1, x2, y )
//   lores.show( bool )
//   color_index = lores.getPixel( x, y )
//   { width: w, height: h } = lores.getScreenSize()
//   
// Example:
//
//   <style>
//     .loresPixel { width: 14px; height: 8px; }
//   </style>
//   <script>
//     lores = new LoRes( document.getElementById( 'lores' ), 40, 40 );
//     interpreter = new BasicInterpreter( tty, lores, paddle );
//   </script>
//   <div id="lores"></div>

/*extern document */

function LoRes( element, columns, rows )
{
    // For references to "this" within callbacks and closures
    var self = this;
    
    self.screenElement = element;
    self.screenWidth = columns;
    self.screenHeight = rows;

    // Colors c/o USENET:
    // Date: Wed, 05 Sep 2007 01:04:20 +0200
    // From: Linards Ticmanis <ticmanis@gmx.de>
    // Newsgroups: comp.sys.apple2
    // Subject: Re: Double hires mode color artifacts
    // Message-ID: <46dde477$0$4527$9b4e6d93@newsspool3.arcor-online.net>

    var colors = [ 
        '#000000', // Black 
        '#901740', // Deep Red 
        '#402ca5', // Dark Blue 
        '#d043e5', // Purple 
        '#006940', // Dark Green 
        '#808080', // Gray 1 
        '#2f95e5', // Medium Blue 
        '#bfabff', // Light Blue 
        '#402400', // Brown        // WAS #405400, error pointed out by MJM
        '#d06a1a', // Orange 
        '#808080', // Gray 2 
        '#ff96bf', // Pink 
        '#2fbc1a', // Light Green 
        '#bfd35a', // Yellow 
        '#6fe8bf', // Aquamarine 
        '#ffffff'  // White 
        ];

    self.color = 0;
    
    var loresPixel = [];

    //----------------------------------------------------------------------
    function init()
    //----------------------------------------------------------------------
    {
        var x, y, html = [], pixel;

        html.push('<table border="0" cellpadding="0" cellspacing="0" style="table-layout: fixed; border-collapse: collapse">');
        html.push('<tbody id="_lores_tbody">');
        for (y = 0; y < self.screenHeight; ++y)
        {
            html.push('<tr class="loresRow">');
            for (x = 0; x < self.screenWidth; ++x)
            {
                html.push( '<td class="loresPixel" lorescolor="0" style="background-color: black;"><'+'/td>' );
            }
            html.push( '</tr>' );
        }
        html.push('</tbody>');
        html.push('</table>');
        self.screenElement.innerHTML = html.join("");

        var tbody = document.getElementById('_lores_tbody');
        for (y = 0; y < self.screenHeight; ++y)
        {
            var row = tbody.childNodes[y];
            for (x = 0; x < self.screenWidth; ++x)
            {
                var elem = row.childNodes[x]; //document.getElementById('_tty_' + x + '_' + y);
                loresPixel[y * self.screenWidth + x] = elem;
            }
        }
        
    } // init
    
    
    //----------------------------------------------------------------------
    this.clear = function()
    //----------------------------------------------------------------------
    {
        var x, y, pixel;
        for( y = 0; y < self.screenHeight; ++y )
        {
            for( x = 0; x < self.screenWidth; ++x )
            {
                pixel = loresPixel[ y * self.screenWidth + x ];
                pixel.style.backgroundColor = "black";
                pixel.setAttribute( "lorescolor", "0" );
            }
        }
        
    }; // clear

    //----------------------------------------------------------------------
    this.setColor = function( color )
    //----------------------------------------------------------------------
    {
        self.color = Math.floor( color ) % colors.length;
    }; // setColor

    //----------------------------------------------------------------------
    this.plot = function( x, y )
    //----------------------------------------------------------------------
    {
        var pixel = loresPixel[ y * self.screenWidth + x ];
        if( pixel )
        {
            pixel.style.backgroundColor = colors[ self.color ];
            pixel.setAttribute( "lorescolor", self.color );
        }
    }; // plot

    //----------------------------------------------------------------------
    this.getPixel = function( x, y )
    //----------------------------------------------------------------------
    {
        var pixel = loresPixel[ y * self.screenWidth + x ];
        if( pixel )
        {
            return parseInt( pixel.getAttribute( "lorescolor" ), 10 );
        }
        else
        {
            return 0;
        }
    }; // getPixel

    //----------------------------------------------------------------------
    this.hlin = function( x1, x2, y )
    //----------------------------------------------------------------------
    {
        var x;
        if( x1 > x2 )
        {
            x = x1;
            x1 = x2;
            x2 = x;
        }
        
        for( x = x1; x <= x2; ++x )
        {
            self.plot( x, y );
        }
    }; // hlin

    //----------------------------------------------------------------------
    this.vlin = function( y1, y2, x )
    //----------------------------------------------------------------------
    {
        var y;
        if( y1 > y2 )
        {
            y = y1;
            y1 = y2;
            y2 = y;
        }
        
        for( y = y1; y <= y2; ++y )
        {
            self.plot( x, y );
        }
    }; // vlin
    
    //----------------------------------------------------------------------
    this.getScreenSize = function()
    //----------------------------------------------------------------------
    {
        return { width: self.screenWidth, height: self.screenHeight };
    }; // getScreenSize
    

    //----------------------------------------------------------------------
    this.show = function( state )
    //----------------------------------------------------------------------
    {
        self.screenElement.style.visibility = state ? "visible" : "hidden";
        
    }; // show

    //----------------------------------------------------------------------
    // Constructor Logic
    //----------------------------------------------------------------------
        
    self.screenElement.innerHTML = "";
        
    init();
}


