/*
 * InputDeviceApp.h
 *
 * Copyright (C) 2003 J. "MUFTI" Scheurich
 * 
 * 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 (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#ifndef _INPUT_DEVICE_APP_H
#define _INPUT_DEVICE_APP_H

#include <string.h>

#ifndef _INPUTDEVICE_H
#include "InputDevice.h"
#endif
#ifndef _ARRAY_H
#include "Array.h"
#endif

class InputDeviceApp {
public:

                        InputDeviceApp() {_maxNumberAxes=0;}


    InputDevice*        getInputDevice(int i) 
                           {
                           if ((i<_inputDevices.size()) && (i>=0))
                              return _inputDevices[i];
                           else
                              return NULL;    
                           }
    int                 getNumberInputDevices(void) 
                           {return _inputDevices.size();}
    int                 setInputDevice(InputDevice* inputdevice)
                           {
                           return replaceOrAddInputDevice(inputdevice,
                                 inputdevice->getDeviceOption(),
                                 inputdevice->getDeviceName());
                           }
    int                 getMaxNumberAxesInputDevices(void)
                           {
                           return _maxNumberAxes;
                           }
    void                accoutMaxNumberAxesInputDevices(void)
                           {
                           int max=0;       
                           for (int i=0;i<_inputDevices.size();i++)
                              if (_inputDevices[i]->get_number_axes()>max)
                                 max=_inputDevices[i]->get_number_axes();
                           _maxNumberAxes=max;
                           }


                        // sort inputdevices, so inputdevices with a readdelay
                        // can prepare the read, while other inputdevices 
                        // can use the time to read data
    void                sortInputDevices(void);

    bool                hasInputDevices(void)
                           {
                           if (_inputDevices.size()>0)
                              {
                              for (int i=0; i < _inputDevices.size(); i++)
                                 if (_inputDevices[i]->isValid()) 
                                    return true;
                              return false;
                              }
                           else
                              return false;
                           }

    bool                has2AxesInputDevices(void)
                           {
                           for (int i=0;i<_inputDevices.size();i++)
                              if (_inputDevices[i]->get_number_axes()==2)
                                 return true;
                           return false;
                           }

    bool                has3AxesInputDevices(void)
                           {
                           for (int i=0;i<_inputDevices.size();i++)
                              if (_inputDevices[i]->get_number_axes()==3)
                                 return true;
                           return false;
                           }

    int                searchInputDevice(const char *option, 
                                         const char *deviceName)
                           {
                           for (int i=0;i<_inputDevices.size();i++)
                              if ((strcmp(_inputDevices[i]->getDeviceOption(),
                                          option) == 0) &&
                                  (strcmp(_inputDevices[i]->getDeviceName(),
                                          deviceName) == 0))
                                 return i;
                           return -1;
                           }

    int                 replaceOrAddInputDevice(InputDevice* newDevice,
                                                const char *option, 
                                                const char *deviceName)
                           {
                           int device = searchInputDevice(option, deviceName);
                           if (device > -1) {
                               delete _inputDevices[device];
                               _inputDevices[device] = newDevice;
                               return device; 
                           } else
                               _inputDevices.append(newDevice); 
                               return _inputDevices.size()-1;
                           }



#ifdef HAVE_AFLOCK
    AflockDevice*       getAflockDevice(int i) 
                           {
                           if ((i<_aflockDevices.size()) && (i>=0))
                              return _aflockDevices[i];
                           else
                              return NULL;    
                           }
    int                 getNumberAflockDevices(void) 
                           {return _aflockDevices.size();}
    int                 setAflockDevice(AflockDevice* aflockDevice)
                           {
                           return replaceOrAddAflockDevice(aflockDevice,
                                 aflockDevice->getDeviceName());
                           }

    int                searchAflockDevice(const char *deviceName)
                           {
                           for (int i=0;i<_aflockDevices.size();i++)
                              if (strcmp(_aflockDevices[i]->getDeviceName(),
                                         deviceName) == 0)
                                 return i;
                           return -1;
                           }

    int                 replaceOrAddAflockDevice(AflockDevice* newDevice,
                                                 const char *deviceName)
                           {
                           int device = searchAflockDevice(deviceName);
                           if (device > -1) {
                               delete _aflockDevices[device];
                               _aflockDevices[device] = newDevice;
                               return device; 
                           } else
                               _aflockDevices.append(newDevice); 
                               return _aflockDevices.size()-1;
                           }

    bool                ReturnTracker(void)
                           {
                           if (_aflockDevices.size()==0)
                              return(false);
                           else
                              for (int i=0;i<_aflockDevices.size();i++)
                                 delete _aflockDevices[i];
                           return(true);
                           } 

    void                stopTrackers(void)
                           {
                           for (int i=0;i<_aflockDevices.size();i++)
                              _aflockDevices[i]->stop();
                           } 

    void                restartTrackers(void)
                           {
                           for (int i=0;i<_aflockDevices.size();i++)
                              _aflockDevices[i]->start();
                           } 
#else
    bool                ReturnTracker(void) {return false;}

#endif
    void                calibrateInputDevices(void)
                           {
                           for (int i=0;i<_inputDevices.size();i++)
                              _inputDevices[i]->set_firstflag();
                           }

    void                increaseInputDevice(TransformMode* tm)
                           {
                           for (int i=0;i<_inputDevices.size();i++) 
                              {
                              if (_inputDevices[i]->isTracker() || 
                                  _inputDevices[i]->isWand()) continue;
                              if (tm->hasTranslation())
                                 {
                                 float factor=_inputDevices[i]->getxyzfactor();
                                 _inputDevices[i]->setxyzfactor(2*factor);
                                 }
                              if (tm->hasRotation())
                                 {
                                 float factor=_inputDevices[i]->getrotfactor();
                                 _inputDevices[i]->setrotfactor(2*factor);
                                 }
                              }
                           }

    void                decreaseInputDevice(TransformMode* tm)
                           {
                           for (int i=0;i<_inputDevices.size();i++) 
                              {
                              if (_inputDevices[i]->isTracker() || 
                                  _inputDevices[i]->isWand()) continue;
                              if (tm->hasTranslation())
                                 {
                                 float factor=_inputDevices[i]->getxyzfactor();
                                 _inputDevices[i]->setxyzfactor(0.5*factor);
                                 }
                             if (tm->hasRotation())
                                 {
                                 float factor=_inputDevices[i]->getrotfactor();
                                 _inputDevices[i]->setrotfactor(0.5*factor);
                                 }
                              }
                           }

private:

    int                 _maxNumberAxes;
    Array<InputDevice*> _inputDevices;
#ifdef HAVE_AFLOCK
    Array<AflockDevice*>_aflockDevices;
#endif
};


#endif

