/*
 * $Id: userPrefs.cxx,v 4.5 2004/06/21 16:12:46 hut66au Exp $
 *
 * Imview, the portable image analysis application
 * http://www.cmis.csiro.au/Hugues.Talbot/imview
 * ----------------------------------------------------------
 *
 *  Imview is an attempt to provide an image display application
 *  suitable for professional image analysis. It was started in
 *  1997 and is mostly the result of the efforts of Hugues Talbot,
 *  Image Analysis Project, CSIRO Mathematical and Information
 *  Sciences, with help from others (see the CREDITS files for
 *  more information)
 *
 *  Imview is Copyrighted (C) 1997-2001 by Hugues Talbot and was
 *  supported in parts by the Australian Commonwealth Science and 
 *  Industry Research Organisation. Please see the COPYRIGHT file 
 *  for full details. Imview also includes the contributions of 
 *  many others. Please see the CREDITS file for full details.
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 * */

/*------------------------------------------------------------------------
 *
 * A user preference panel using fluid.
 *
 * Hugues Talbot	18 Oct 1998
 *      
 *-----------------------------------------------------------------------*/

#include "imnmspc.hxx"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <string>
#include <sstream>

#include "imview.hxx"
#include "imageIO.hxx"
#include "imageViewer.hxx"
#include "nocase.hxx"
#include "userPrefs.hxx"
#include "io/newprefio.hxx"

// some extern defs
extern imprefs     *fileprefs;
extern imageViewer *mainViewer;
extern imageIO     *IOBlackBox;
extern int    debugIsOn;
extern int    stopDebug;
extern char   currentprefspath[];


using std::string;
using std::ostringstream;

// user preferences panel methods
userprefs::userprefs()
{
    dbgprintf("User preferences panel constructed\n");
    userprefsWindow = 0; // fluid depends on that
    return;
}

void userprefs::setDefaults()
{
    char dblval[20];
    
    if (fileprefs != 0) {
	// general stuff
	pathToPrefsInput->value(fileprefs->prefspath());
	if (fileprefs->smoothZoomout()) 
	    smoothWhenZoomoutButton->set();
	else
	    smoothWhenZoomoutButton->clear();
	
	if (fileprefs->keepPoints())
	    keepPointsButton->set();
	else
	    keepPointsButton->clear();
	
	if (fileprefs->mouseZoomType() == ZOOM_UNCONSTRAINED) {
	    constrainZoomCheck->clear();
	    unconstrainZoomCheck->set();
	} else {
	    constrainZoomCheck->set();
	    unconstrainZoomCheck->clear();
	}

	transparencyValueSlider->value(fileprefs->overlayTransparency());
	
	// PS stuff
	pathToGsInput->value(fileprefs->gspath());
	sprintf(dblval, "%d", (int)(fileprefs->psRenderRes()));
	renderInput->value(dblval);
	sprintf(dblval, "%d", (int)(fileprefs->psDisplayRes()));
	displayInput->value(dblval);
	// clear everything
	greyCheck->clear();
	colourCheck->clear();
	bwCheck->clear();
	switch (fileprefs->psRenderDepth()) {
	  case PSREND_GREY:
	    greyCheck->set();
	    break;
	  case PSREND_COLOUR:
	    colourCheck->set();
	    break;
	  default:
	    bwCheck->set();
	    break;
	}
	if (fileprefs->psRenderSmooth())
	    smoothButton->set();
	else
	    smoothButton->clear();

        if (fileprefs->psAntialiasRender())
            antialiasButton->set();
        else
            antialiasButton->clear();

        boundingChoice->value(fileprefs->psBoundingBox());
	
	// Server stuff
	sprintf(dblval, "%g", fileprefs->pollFrequency());
	pollFrequencyInput->value(dblval);
	pollFrequencySlider->value(log(fileprefs->pollFrequency())/(2*log(10.0)) - 0.5);
	
	if (fileprefs->requirePassword())
	    securityPasswordButton->set();
	else
	    securityPasswordButton->clear();

	if (fileprefs->localhostOnly()) 
	    securityLocalhostButton->set();
	else
	    securityLocalhostButton->clear();
        
        // expert stuff
        if (fileprefs->hideMenu())
            hideMenuButton->set();
        else
            hideMenuButton->clear();

	// Hack stuff
	xorValueBreakLineInput->value(fileprefs->xorBreakLines());
	xorValueProfileLineInput->value(fileprefs->xorProfileLines());
    }
    
    return;
}

// revert to saved
void userprefs::revertPrefs()
{
    fileprefs->readprefs(currentprefspath);
}

// save current.
void userprefs::savePrefs()
{
    fileprefs->writeprefs(pathToPrefsInput->value());
}

void userprefs::show()
{
    userprefsWindow->show();
    return;
}

void userprefs::hide()
{
    userprefsWindow->hide();
    return;
}

// a hash string to find out if things have changed between PS renderings
string userprefs::getPsPrefsHash()
{
    ostringstream osm;

    if (userprefsWindow != NULL) {
        // a CSV string
        osm << pathToGsInput->value()     << ','
            << renderInput->value()     << ','
            << renderInput->value()     << ','
            << renderInput->value()     << ','
            << greyCheck->value()       << ','
            << bwCheck->value()         << ','
            << smoothButton->value()    << ','
            << antialiasButton->value() << ','
            << boundingChoice->value();
    } else 
        osm << "Unknown";

    return osm.str();
}

// the callbacks


// General tab

void prefbrowse_cb(Fl_Button *, userprefs *panel)
{
    dbgprintf("Preference file browse button callback\n");
    return;
}

void smoothzoomout_cb(Fl_Round_Button *b, userprefs *panel)
{
    dbgprintf("Smooth zoomout button callback\n");
    if (b->value())
	fileprefs->smoothZoomout(true);
    else
	fileprefs->smoothZoomout(false);
    return;
}

void keeppoints_cb(Fl_Round_Button *b, userprefs *panel)
{
    dbgprintf("Keep points button callback\n");
    if (b->value())
	fileprefs->keepPoints(true);
    else
	fileprefs->keepPoints(false);
    return;
}

void constrainedzoom_cb(Fl_Check_Button *, userprefs *panel)
{
    dbgprintf("Constrained check button callback\n");
    fileprefs->mouseZoomType(ZOOM_CONSTRAINED);
    return;
}

void unconstrainedzoom_cb(Fl_Check_Button *, userprefs *panel)
{
    dbgprintf("Unconstrained check button callback\n");
    fileprefs->mouseZoomType(ZOOM_UNCONSTRAINED);
    return;
}

void transparency_cb(Fl_Value_Slider *s, userprefs *panel)
{
    dbgprintf("Transparency value slider callback\n");
    fileprefs->overlayTransparency(s->value());
    //IOBlackBox->applyOverlayToCurrentImage();
    IOBlackBox->applyImageParameters(0, 0, 0, true);
    mainViewer->displayCurrentImage(); // this should take the new transparency into account
}

// PS tab
void pathtogsinput_cb(Fl_Input *s, userprefs *)
{
    dbgprintf("Path to GS input callback\n");
    fileprefs->gspath(s->value());
    return;
}

void pathtogvinput_cb(Fl_Input *s, userprefs *)
{
    dbgprintf("Path to Previewer input callback\n");
    
    fileprefs->gvpath(s->value());
    return;
}

void gsbrowse_cb(Fl_Button *, userprefs *panel)
{
    dbgprintf("GS path browse button callback\n");
    return;
}

void renderinput_cb(Fl_Int_Input *s, userprefs *)
{
    dbgprintf("Rendering resolution input callback\n");
    fileprefs->psRenderRes((double)(atof(s->value())));
    return;
}

void displayinput_cb(Fl_Int_Input *s, userprefs *)
{
    dbgprintf("Display resolution input callback\n");
    fileprefs->psDisplayRes((double)(atof(s->value())));
    return;
}


void colourcheck_cb(Fl_Check_Button *, userprefs *)
{
    dbgprintf("Colour check button callback\n");
    fileprefs->psRenderDepth(PSREND_COLOUR);
    return;
}

void greycheck_cb(Fl_Check_Button *, userprefs *)
{
    dbgprintf("Grey check button callback\n");
    fileprefs->psRenderDepth(PSREND_GREY);
    return;
}

void bwcheck_cb(Fl_Check_Button *, userprefs *)
{
    dbgprintf("BW check button callback\n");
    fileprefs->psRenderDepth(PSREND_BW);
    return;
}

void smoothbutton_cb(Fl_Round_Button *b, userprefs *)
{
    dbgprintf("Smooth button callback\n");
    if (b->value())
	fileprefs->psRenderSmooth(true);
    else
	fileprefs->psRenderSmooth(false);
    return;
}

void aabutton_cb(Fl_Round_Button *b, userprefs *)
{
    dbgprintf("Antialias button callback\n");
    if (b->value())
        fileprefs->psAntialiasRender(true);
    else 
         fileprefs->psAntialiasRender(false);
    return;
}

void boundingchoice_cb(Fl_Choice *b, userprefs *)
{
    dbgprintf("Bounding box choice callback with value %d\n", b->value());
    fileprefs->psBoundingBox((page_size)(b->value()));
    return;
}

// Server Tab
void pollslider_cb(Fl_Slider *s, userprefs *up)
{
    double v, nv;
    
    dbgprintf("Poll frequency slider callback\n");
    v = s->value();
    nv = ceil(pow(10,2*v+1));

    // update the input field accordingly
    up->setInputHz(nv);
    // tell the preference manager
    fileprefs->pollFrequency(nv);
    return;
}

void pollinput_cb(Fl_Float_Input *i, userprefs *up)
{
    double v, nv;
    char   cv[20];
    
    dbgprintf("Poll frequency input callback\n");
    v = atof(i->value());
    if (v <= 1) { // we can cheat a little and enter low values 
	v = 10; // 10 Hz only the official minimum
	sprintf(cv, "%g", v);
	i->value(cv);
    } else if (v > 5000) { // 5kHz maxi, this is pushing it... 
	v = 1000;
	sprintf(cv, "%g", v);
	i->value(cv);
    }

    nv = log(v)/(2*log(10.0)) - 0.5; // do the computation yourself!

    // update the slider
    up->setSliderHz(nv);
    // tell the preference manager
    fileprefs->pollFrequency(nv);
    
    return;
}

void requirepassword_cb(Fl_Round_Button *b, userprefs *up)
{
    dbgprintf("Require password callback\n");
    if (b->value())
	fileprefs->requirePassword(true);
    else
	fileprefs->requirePassword(false);
    return;
}

void localhostonly_cb(Fl_Round_Button *b, userprefs *up)
{
    dbgprintf("local host only callback\n");
    if (b->value())
	fileprefs->localhostOnly(true);
    else
	fileprefs->localhostOnly(false);
    return;
}
    
// Expert tab

void hidemenu_cb(Fl_Round_Button *b, userprefs *)
{
    dbgprintf("hide menu callback\n");
    if (b->value())
        fileprefs->hideMenu(true);
    else
        fileprefs->hideMenu(false);
    return;
} 

// Hack Tab
void showdebug_cb(Fl_Round_Button *, userprefs *)
{
    dbgprintf("Debug button callback\n");
    debugIsOn = !debugIsOn;
    return;
}

void stopdebug_cb(Fl_Round_Button *, userprefs *)
{
    dbgprintf("Stop button callback\n");
    stopDebug = !stopDebug;
    return;
}

void xorbreakline_cb(Fl_Input *s, userprefs *)
{
    dbgprintf("XOR break line callback\n");
    fileprefs->xorBreakLines(s->value());
    
    return;
}

void xorprofileline_cb(Fl_Input *s, userprefs *panel)
{
    dbgprintf("XOR profile line callback\n");
    fileprefs->xorProfileLines(s->value());
    
    return;
}

// main buttons

void cancelbutton_cb(Fl_Button *, userprefs *panel)
{
    dbgprintf("Cancel Button pressed on user prefs panel\n");
    // revert to saved prefs
    panel->revertPrefs();
    // hide the window, do nothing
    panel->hide();
    return;
}


void savebutton_cb(Fl_Button *, userprefs *panel)
{
    dbgprintf("Save Button pressed on user prefs panel\n");
    // do the preference savings.
    panel->savePrefs();
    return;
}

void okbutton_cb(Fl_Return_Button *, userprefs *panel)
{
    dbgprintf("OK Button pressed on print prefs panel\n");
    panel->hide();
    return;
}
