﻿
var pageWidth = 950;
var fieldHieght = 23;
var rowHieght = 16;
var titleBarHeight = 18;
var headerHeight = 15;
var footerHeight = 20;
var columnPadding = 4;
var pixelsPerCharacter = 9;

var darkBlue = "#1111AA";
var mediBlue = "#AABBFF";
var liteBlue = "#D0E0FF";

function SearchPage(be)
{
    this.be = be;
    
    this.criteriaPanel = new DataPanel(be);
    this.dataList = new DataList(be);
}

SearchPage.prototype.Draw = function(plugin, rootCanvas)
{
    var d = new Drawer( plugin );

    var critHeight = titleBarHeight + this.criteriaPanel.Rows()*fieldHieght;

    this.DrawCriteriaPanel( d, rootCanvas, critHeight );
    this.DrawDataList( d, rootCanvas, critHeight );
}

SearchPage.prototype.DrawCriteriaPanel = function(d, rootCanvas, critHeight)
{
    // Criteria 
    var critCanvas = d.AddCanvas( rootCanvas, 20, 20 );
    
    // Title
    d.AddRectangle( critCanvas, { Width: pageWidth, Height:50, Fill:darkBlue, RadiusX:10, RadiusY:10, Clip: {x:0,y:0,Width:pageWidth,Height:titleBarHeight} } );
    d.AddTextBlock( critCanvas, this.be.title, { Foreground: "White", x:16, y:-1 } );

    // Background
    d.AddRectangle( critCanvas, { Width: pageWidth, Height:critHeight, Fill:mediBlue, RadiusX:10, RadiusY:10, Clip: {x:0,y:titleBarHeight,Width:pageWidth,Height:critHeight-titleBarHeight} } );

    // Fields (divided into columns)
    var xOffset = 0;
    for (var colInx = 0; colInx < this.criteriaPanel.numberOfColumns; colInx++)
    {
        var col = this.criteriaPanel.GetFieldsInColumn( colInx );

        // Column for Labels
        var labelColumnWidth = this.criteriaPanel.LabelColumnWidth( d, colInx );
        var labelsCanvas = d.AddCanvas( critCanvas, xOffset, titleBarHeight );
        for (var rowInx = 0; rowInx < col.length; rowInx++)
        {
            var field = col[rowInx];
            var txtBlock = field.XamlLabel( d, rowInx );
            txtBlock["Canvas.Left"] =  ( labelColumnWidth - txtBlock.ActualWidth ) - columnPadding;
            labelsCanvas.children.add( txtBlock );
        }
        xOffset += labelColumnWidth;

        // Column for Controls
        var controlColumnWidth = this.criteriaPanel.ControlColumnWidth( colInx );
        var controlsCanvas = d.AddCanvas( critCanvas, xOffset, titleBarHeight );
        if ( colInx+1 == this.criteriaPanel.numberOfColumns ) // Then it extends to the far-right (and must be clipped).
            d.AddRectangle( controlsCanvas, { Width: (pageWidth-xOffset)+20, Height:critHeight, Fill:liteBlue, RadiusX:10, RadiusY:10, x:-20, y:-titleBarHeight, Clip: {x:20,y:titleBarHeight,Width:pageWidth-xOffset,Height:critHeight} } );
        else
            d.AddRectangle( controlsCanvas, { Width: controlColumnWidth, Height:critHeight-titleBarHeight, Fill:liteBlue } );
        var yOffset = 4;
        for (var inx = 0; inx < col.length; inx++)
        {
            var field = col[inx];
            var size = field.PMD().GetSize();
            var controlWidth = size * pixelsPerCharacter;

            d.AddRectangle( controlsCanvas, { Width: controlWidth, Height:18, Fill:"White", x:columnPadding, y:yOffset } );
            yOffset += fieldHieght;
        }        
        xOffset += controlColumnWidth;
    }

    // Buttons
    var searchButtonCanvas = d.AddCanvas( critCanvas, pageWidth-90, critHeight-50 );
    d.AddRectangle( searchButtonCanvas, { Width: 80, Height:19, Fill:"#6688E0", Stroke:"Black", StrokeThickness:"2" } );
    d.AddTextBlock( searchButtonCanvas, "search", { Foreground: "White", x:24, y:3, FontSize:10 } );

    var searchButtonCanvas = d.AddCanvas( critCanvas, pageWidth-90, critHeight-25 );
    d.AddRectangle( searchButtonCanvas, { Width: 80, Height:19, Fill:"#6688E0", Stroke:"#AACCFF", StrokeThickness:"2" } );
    d.AddTextBlock( searchButtonCanvas, "clear", { Foreground: "White", x:28, y:3, FontSize:10 } );
}
SearchPage.prototype.DrawDataList = function(d, rootCanvas, critHeight)
{
    var canvas = d.AddCanvas( rootCanvas, 20, critHeight+40 );
    
    var dataListHeight = titleBarHeight + headerHeight + this.dataList.pageSize*rowHieght + footerHeight;

    // Title
    d.AddRectangle( canvas, { Width: pageWidth, Height:50, Fill:darkBlue, RadiusX:10, RadiusY:10, Clip: {x:0,y:0,Width:pageWidth,Height:titleBarHeight} } );
    d.AddTextBlock( canvas, "Search Results", { Foreground: "White", x:420, y:-1 } );

    // Header + Rows
    this.dataList.Draw( d, canvas, { showFooter:true } );
}



function EMP(be)
{
    this.be = be;
    
    this.dataList = new DataList(be);
    this.dataList.pageSize = 10;

    this.dataPanel = new DataPanel(be);
}

EMP.prototype.Draw = function(plugin, rootCanvas)
{
    var d = new Drawer( plugin );

    var dataListHeight = titleBarHeight + headerHeight + this.dataList.pageSize*rowHieght;

    this.DrawDataList(d, rootCanvas, dataListHeight);
    this.DrawDataPanel(d, rootCanvas, dataListHeight);
}
    
EMP.prototype.DrawDataList = function(d, rootCanvas, dataListHeight)
{
    var canvas = d.AddCanvas( rootCanvas, 20, 20 );
    
    // Title
    d.AddRectangle( canvas, { Width: pageWidth, Height:50, Fill:darkBlue, RadiusX:10, RadiusY:10, Clip: {x:0,y:0,Width:pageWidth,Height:titleBarHeight} } );
    d.AddTextBlock( canvas, this.be.title, { Foreground: "White", x:40, y:-1 } );

    // Header + Rows
    this.dataList.Draw( d, canvas, { showFooter:false, selectedInx:4 } );

    // Divider
    d.AddTextBlock( canvas, "Type changes below.", { Foreground: "Black", x:400, y:dataListHeight, FontSize:12 } );
}
EMP.prototype.DrawDataPanel = function(d, rootCanvas, dataListHeight)
{
    var canvas = d.AddCanvas( rootCanvas, 20, dataListHeight+20 );

    var panelHeight = this.dataPanel.Rows()*fieldHieght;

    // Background for DataPanel
    d.AddRectangle( canvas, { Width: pageWidth, Height:panelHeight, Fill:mediBlue, RadiusX:10, RadiusY:10, Clip: {x:0,y:titleBarHeight,Width:pageWidth,Height:panelHeight-titleBarHeight} } );

    // Fields (divided into columns)
    var xOffset = 0;
    for (var colInx = 0; colInx < this.dataPanel.numberOfColumns; colInx++)
    {
        var col = this.dataPanel.GetFieldsInColumn( colInx );

        // Column for Labels
        var labelColumnWidth = this.dataPanel.LabelColumnWidth( d, colInx );
        var labelsCanvas = d.AddCanvas( canvas, xOffset, titleBarHeight );
        for (var rowInx = 0; rowInx < col.length; rowInx++)
        {
            var field = col[rowInx];
            var txtBlock = field.XamlLabel( d, rowInx );
            txtBlock["Canvas.Left"] =  ( labelColumnWidth - txtBlock.ActualWidth ) - columnPadding;
            labelsCanvas.children.add( txtBlock );
        }
        xOffset += labelColumnWidth;

        // Column for Controls
        var controlColumnWidth = this.dataPanel.ControlColumnWidth( colInx );
        var controlsCanvas = d.AddCanvas( canvas, xOffset, titleBarHeight );
        if ( colInx+1 == this.dataPanel.numberOfColumns ) // Then it extends to the far-right (and must be clipped).
            d.AddRectangle( controlsCanvas, { Width: (pageWidth-xOffset)+20, Height:panelHeight, Fill:liteBlue, RadiusX:10, RadiusY:10, x:-20, y:-titleBarHeight, Clip: {x:20,y:titleBarHeight,Width:pageWidth-xOffset,Height:panelHeight} } );
        else
            d.AddRectangle( controlsCanvas, { Width: controlColumnWidth, Height:panelHeight-titleBarHeight, Fill:liteBlue } );
        var yOffset = 4;
        for (var inx = 0; inx < col.length; inx++)
        {
            var field = col[inx];
            var size = field.PMD().GetSize();
            var controlWidth = size * pixelsPerCharacter;

            d.AddRectangle( controlsCanvas, { Width: controlWidth, Height:18, Fill:"White", x:columnPadding, y:yOffset } );
            yOffset += fieldHieght;
        }        
        xOffset += controlColumnWidth;
    }

    // Buttons
    var searchButtonCanvas = d.AddCanvas( canvas, pageWidth-90, panelHeight-50 );
    d.AddRectangle( searchButtonCanvas, { Width: 80, Height:19, Fill:"#6688E0", Stroke:"Black", StrokeThickness:"2" } );
    d.AddTextBlock( searchButtonCanvas, "add", { Foreground: "White", x:30, y:3, FontSize:10 } );

    var searchButtonCanvas = d.AddCanvas( canvas, pageWidth-90, panelHeight-25 );
    d.AddRectangle( searchButtonCanvas, { Width: 80, Height:19, Fill:"#6688E0", Stroke:"#AACCFF", StrokeThickness:"2" } );
    d.AddTextBlock( searchButtonCanvas, "delete", { Foreground: "White", x:25, y:3, FontSize:10 } );
}


function DataList(be)
{
    this.be = be;
    this.columns = new Array();
    this.pageSize = 20;
}
DataList.prototype.AddBoundTextBox = function( dataField )
{
    var textBox = new BoundTextBox( dataField );
    this.AddColumn( textBox );
}
DataList.prototype.AddColumn = function( boundIcColumn )
{
    this.columns.push( boundIcColumn );
    boundIcColumn.dataGrid = this;
}
DataList.prototype.Draw = function( d, canvas, parms )
{
    var dataListHeight = titleBarHeight + headerHeight + this.pageSize*rowHieght + (parms.showFooter?footerHeight:0);

    // Background
    if (parms.showFooter)
        d.AddRectangle( canvas, { Width: pageWidth, Height:dataListHeight, Fill:liteBlue, RadiusX:10, RadiusY:10, Clip: {x:0,y:titleBarHeight,Width:pageWidth,Height:dataListHeight-titleBarHeight} } );
    else
        d.AddRectangle( canvas, { Width: pageWidth, Height:dataListHeight-titleBarHeight, Fill:liteBlue, y:titleBarHeight} );

    // Rows
    var widths = new Array();
    for (var colInx = 0; colInx < this.columns.length; colInx++)
        widths[colInx] = 0;

    var rowsCanvas = d.AddCanvas( canvas, 0, 0 );
    var yOffset = titleBarHeight + headerHeight;
    for (var rowInx = 0; rowInx < this.pageSize; rowInx++)
    {
        var rowCanvas = d.AddCanvas( rowsCanvas, 0, yOffset );

        var fontColor = "Black";
        if (rowInx == parms.selectedInx)
            d.AddRectangle( rowCanvas, { Width: pageWidth, Height:rowHieght, Fill:darkBlue } ), fontColor="White";
        else if (rowInx % 2 == 0)
            d.AddRectangle( rowCanvas, { Width: pageWidth, Height:rowHieght, Fill:"#D0FCFF" } );

        var rowCanvas2 = d.AddCanvas( rowCanvas, 20, 3 );

        for (var colInx = 0; colInx < this.columns.length; colInx++)
        {
            var col = this.columns[ colInx ];
            var txtBlock = d.AddTextBlock( rowCanvas2, col.PMD().GetSampleText(), { Foreground: fontColor, x:0, FontSize:"9", FontFamily:"Verdana" } );
            widths[colInx] = Math.max( txtBlock.ActualWidth, widths[colInx] );
        }

        yOffset += rowHieght;
    }

    // Header
    var headerCanvas = d.AddCanvas( canvas, 20, 20 );
    var xOffset = 0;
    for (var colInx = 0; colInx < this.columns.length; colInx++)
    {
        var col = this.columns[ colInx ];
        var headerTxtBlock = d.AddTextBlock( headerCanvas, col.Label(), { Foreground: "Black", x:xOffset, FontSize:"9", FontWeight:"ExtraBlack", FontFamily:"Verdana" } );
        widths[colInx] = Math.max( headerTxtBlock.ActualWidth, widths[colInx] );
        xOffset += widths[colInx] + 20;
    }

    // Reset width of each row cell
    for (var rowInx = 0; rowInx < this.pageSize; rowInx++)
    {
        var rowCanvas = rowsCanvas.children.getItem( rowInx );
        var rowCanvas2 = rowCanvas.children.getItem( (rowInx % 2 == 0)?1:0 );

        var xOffset = 0;
        for (var colInx = 0; colInx < this.columns.length; colInx++)
        {
            var txtBlock = rowCanvas2.children.getItem( colInx );
            txtBlock["Canvas.Left"] = xOffset;
            xOffset += widths[colInx]+20;
        }
    }

    // Footer/Pager 
    if ( parms.showFooter )
    {
        var footerCanvas = d.AddCanvas( canvas, 400, dataListHeight-footerHeight );
        d.AddTextBlock( footerCanvas, "1", { Foreground: "Red", x:0, FontSize:"12", FontFamily:"Verdana", FontWeight:"ExtraBlack" } );
        d.AddTextBlock( footerCanvas, "2", { Foreground: "Black", x:20, FontSize:"12", FontFamily:"Verdana" } );
        d.AddTextBlock( footerCanvas, "Next >", { Foreground: "Black", x:40, FontSize:"12", FontFamily:"Verdana" } );
    }
}

function DataPanel(be)
{
    this.be = be;
    this.fields = new Array();
    this.numberOfColumns = 2;
}
DataPanel.prototype.AddBoundTextBox = function( dataField, parms )
{
    var textBox = new BoundTextBox( dataField, parms );
    this.AddField( textBox );
}
DataPanel.prototype.AddField = function( boundIcColumn )
{
    this.fields.push( boundIcColumn );
    boundIcColumn.dataGrid = this;
}
DataPanel.prototype.GetFieldsInColumn = function( columnInx )
{
    var col = new Array();
    for (var inx = 0; inx < this.fields.length; inx++)
    {
        if (inx % this.numberOfColumns == columnInx)
            col.push( this.fields[inx] );
    }
    return col;
}
DataPanel.prototype.Rows = function()
{
    var rows = parseInt(this.fields.length/2) + (this.fields.length%2);
    return Math.max( rows, 3 );
}
DataPanel.prototype.LabelColumnWidth = function( drawer, columnInx )
{
    var col = this.GetFieldsInColumn( columnInx );

    var maxLabelWidth = 0;
    for (var rowInx = 0; rowInx < col.length; rowInx++)
    {
        var field = col[rowInx];
        var txtBlock = field.XamlLabel( drawer, rowInx );
        maxLabelWidth = Math.max( maxLabelWidth, txtBlock.ActualWidth );
    }

    return maxLabelWidth + (columnPadding*2);
}

DataPanel.prototype.ControlColumnWidth = function( columnInx )
{
    var col = this.GetFieldsInColumn( columnInx );

    var maxControlWidth = 0;
    for (var rowInx = 0; rowInx < col.length; rowInx++)
    {
        var field = col[rowInx];
        var size = field.PMD().GetSize();
        var controlWidth = size * pixelsPerCharacter;
        maxControlWidth = Math.max( maxControlWidth, controlWidth );
    }

    return maxControlWidth + (columnPadding*2);
}


function BoundTextBox( dataField, parms )
{
    if (!parms)
        parms = {};

    this.dataField = dataField;
    this.dataGrid = null;    
    this.required = (parms.Required) ? true : false;
    this.ddl = (parms.DDL) ? true : false;
}
BoundTextBox.prototype.PMD = function()
{
    if ( this.dataField.toLowerCase() == "businessentitystatus" )
        return PropertyMetaData.BES;
    else
        return this.dataGrid.be.GetProperty( this.dataField );
}
BoundTextBox.prototype.Label = function()
{
    return this.PMD().label + (this.required?"*":"");
}
BoundTextBox.prototype.XamlLabel = function( drawer, rowInx )
{
    if ( this._txtBlock == null )
    {
        var yOffset = 2 + (rowInx * fieldHieght);
        this._txtBlock = drawer.CreateTextBlock( this.Label(), { Foreground: "Black", x:columnPadding, y:yOffset } );
    }
    return this._txtBlock;
}

function BusinessEntity( title )
{
    this.title = title;
    this.properties = new Array();
}
BusinessEntity.prototype.GetProperty = function( label )
{
    for (var inx = 0; inx < this.properties.length; inx++)
    {
        var pmd = this.properties[inx];
        if (pmd.label == label)
            return pmd;
    }
    return null;
}


var DataType = 
    {
        NUMBER:     1,
        STRING:     2,
        CURRENCY:   3,
        DATE:       4,
        
        EOF: null // to protect comma mistakes
    };



function PropertyMetaData( label, dataType, size )
{
    this.label = label;
    this.dataType = dataType;
    this.size = size;
}
PropertyMetaData.BES = new PropertyMetaData("", DataType.STRING, 5);
PropertyMetaData.prototype.GetSize = function()
{
    switch ( this.dataType )
    {
        case DataType.DATE:
            return 8;
        case DataType.STRING:
            return Math.min(30, this.size);
        default:
            return this.size;
    }
}
PropertyMetaData.prototype.GetSampleText = function()
{
    if (this === PropertyMetaData.BES)
        return Math.random() > 0.9 ? "A" : Math.random() > 0.8 ? "M" : Math.random() > 0.7 ? "D" : "";

    switch ( this.dataType )
    {
        case DataType.DATE:
            var d = new Date( parseInt(Math.random()*999999999999) );
            return d.getMonth()+1 +"/"+ d.getDate() +"/"+ d.getFullYear();
        default:
            var str = "";
            var ch = "A";
            for (var inx = 0; inx < this.GetSize(); inx++)
            {
                var oneTo5 = parseInt( Math.random() * 5 )+1;
                if ( inx > 0 && oneTo5 == 3 )
                {
                    str += " ";
                    ch = "A";
                }
                else
                {
                    var zeroTo25 = parseInt( Math.random() * 26 );
                    str += String.fromCharCode( ch.charCodeAt(0) + zeroTo25 );
                    ch = "a";
                }
            }            
            return str;//"".pad(this.GetSize(), "XXXX ");
    }
}


String.prototype.pad = function(l, s, t)
{
	return s || (s = " "), (l -= this.length) > 0 ? (s = new Array(Math.ceil(l / s.length)
		+ 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2))
		+ this + s.substr(0, l - t) : this;
};

