// $Id: twodtable.cpp,v 1.9 2018/01/03 21:33:01 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

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.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#include <string>
#include <vector>
#include "display.h"
#include "menu_strings.h"
#include "twodtable.h"
#include "ui_interface.h"
#include "stringx.h"

using std::string;
using std::vector;

static const long MAXDISPLAYWIDTH = 78;

TwoDTable::TwoDTable(UIInterface & myui)
    : ui(myui)
{
}

TwoDTable::~TwoDTable()
{
}

bool TwoDTable::IsVisible()
{
    return true;
}

string TwoDTable::RowHeader(UIInterface &)
{
    return menustr::emptyString;
}

string TwoDTable::CreateDisplayString()
{
    return CreateDisplayString(ui);
}

string TwoDTable::CreateDisplayString(UIInterface & ui)
{
    if(!IsVisible()) return menustr::emptyString;

    long rowMax = RowCount(ui);
    long colMax = ColCount(ui);
    long colIndex, rowIndex;
    StringVec2d outv;
    LongVec1d widths;

    // create column header row
    vector<string> colHeader;
    colHeader.push_back(RowHeader(ui));
    for(colIndex = 0; colIndex < colMax; colIndex++)
    {
        colHeader.push_back(ColLabel(ui,colIndex));
    }
    bool someActualHeaders = false;
    for (unsigned long c=0; c<colHeader.size(); c++)
    {
        if (colHeader[c] != menustr::emptyString)
        {
            someActualHeaders = true;
        }
    }
    if (someActualHeaders)
    {
        outv.push_back(colHeader);
    }

    // create data rows
    for(rowIndex = 0; rowIndex < rowMax; rowIndex++)
    {
        vector<string> row;
        row.push_back(RowLabel(ui,rowIndex));
        for(colIndex = 0; colIndex < colMax; colIndex++)
        {
            row.push_back(Cell(ui,rowIndex,colIndex));
        }
        outv.push_back(row);
    }

    // calculate data widths
    for(unsigned long i=0;i<outv[0].size();i++)
    {
        widths.push_back(0);
    }
    // calculate appropriate column widths
    for(unsigned long r=0;r<outv.size();r++)
    {
        for(unsigned long c=0;c<outv[r].size();c++)
        {
            long curr_width = outv[r][c].length();
            if(curr_width > widths[c])
            {
                widths[c] = curr_width;
            }
        }
    }
    // Re-calculate column widths, given that we can only be 78 characters wide.
    long total_width = 0;
    for (unsigned long i=0; i<widths.size(); i++)
    {
        total_width += widths[i];
        total_width++; //for the space between columns
    }
    while (total_width > MAXDISPLAYWIDTH)
    {
        long difference = total_width - MAXDISPLAYWIDTH;
        unsigned long maxwidth=0;
        for (unsigned long i=1; i < widths.size(); i++)
        {
            if (widths[i] > widths[maxwidth])
            {
                maxwidth = i;
            }
        }
        long reduce = std::min(5L, difference);
        reduce = std::min(reduce, (widths[maxwidth]-3));
        if (reduce == widths[maxwidth]-3)
        {
            reduce = 1;
        }
        widths[maxwidth] -= reduce;
        total_width -= reduce;
    }

    // create string
    string outputString = "";
    outputString += Title(ui);
    outputString += "\n";
    for(unsigned long r=0;r<outv.size();r++)
    {
        StringVec2d wrappedLines;
        unsigned long numlines = 1;
        for(unsigned long c=0;c<outv[r].size();c++)
        {
            StringVec1d wrappedCell;
            wrappedCell = Linewrap(outv[r][c], (widths[c]), 2);
            wrappedLines.push_back(wrappedCell);
            if (wrappedCell.size() > numlines)
            {
                numlines = wrappedCell.size();
            }
        }
        for (unsigned long r2=0; r2<numlines; r2++)
        {
            for (unsigned long c=0; c<wrappedLines.size(); c++)
            {
                outputString += " ";
                if (wrappedLines[c].size() > r2 )
                {
                    outputString += MakeJustified(wrappedLines[c][r2],-(widths[c]));
                }
                else
                {
                    outputString += MakeJustified("",-(widths[c]));
                }
            }
            outputString += "\n";
        }
    }
    return outputString;
}

//____________________________________________________________________________________
