/* 
 *  SelectorDialog.cpp
 *
 *	Copyright (C) Alberto Vigata - January 2000
 *
 *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
 *	
 *  FlasKMPEG 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, or (at your option)
 *  any later version.
 *   
 *  FlasKMPEG 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 GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

#include <windows.h>
#include "resource.h"

#include "selectordialog.h"
//global
TSelectorDialog   *set;
CArr <int>        listbox_mirror;


/* Rendering selections */
void RenderSectionSelection(HWND hDlg, int section)
{
	int i;  
	for(i=0; i<set->strings[section].GetCount(); i++)
	{
		if( set->selected[section][i] )
			SendDlgItemMessage( hDlg, IDC_SELECTOR, LB_SELITEMRANGE, true,MAKELPARAM(set->first_in_section[section]+i,set->first_in_section[section]+i ));
	}
}
void RenderSelection( HWND hDlg )
{
	int i;
	// First, unselect all items
	int list_items = SendDlgItemMessage( hDlg, IDC_SELECTOR, LB_GETCOUNT   , 0     , 0);
	for( i=0; i<list_items; i++)
		SendDlgItemMessage( hDlg, IDC_SELECTOR, LB_SELITEMRANGE, false, MAKELPARAM(i,i) );
	// Now, render selections
	for(i=0; i<set->section_count; i++)
		RenderSectionSelection(hDlg, i);
}
void MirrorList(HWND hDlg, CArr<int> &array)
{

	int placed,i;

	int list_items = SendDlgItemMessage( hDlg, IDC_SELECTOR, LB_GETCOUNT   , 0     , 0);
	int	*selected  = new int[list_items];
	placed         = SendDlgItemMessage( hDlg, IDC_SELECTOR, LB_GETSELITEMS, list_items, (LPARAM)selected);


	//reset current array
	array.SetArraySize(list_items);
	for(i=0; i<list_items; i++)
		 array[i] = 0;
	// mark selected items
	for(i=0; i<placed; i++)
		 array[ selected[i] ] = 1;
	delete [] selected;
}


/* Section handling */
int  GetSection(HWND hDlg, int listbox_item)
{
	int i;
	CArr<int>      current_selected;
	MirrorList(hDlg, current_selected);

	for(i=0; i<set->section_count; i++)
	{
		if(listbox_item>= set->first_in_section[i]   &&
		   listbox_item<= set->last_in_section[i])
		   return i;
	}
	return 0;
}

int  GetSectionPos(HWND hDlg, int listbox_item)
{
	int i;
	CArr<int>      current_selected;
	MirrorList(hDlg, current_selected);

	for(i=0; i<set->section_count; i++)
	{
		if(listbox_item>= set->first_in_section[i]   &&
		   listbox_item<= set->last_in_section[i])
		   return listbox_item - set->first_in_section[i];
	}
	return 0;
}
int GetSectionSelCount(HWND hDlg, int section)
{
	int selected=0,i;
	for(i=0; i<set->strings[section].GetCount(); i++)
	{
		if(set->selected[section][i])
			selected++;
	}
	return selected;
}
bool ItemIsInSection(HWND hDlg, int item)
{
	int i;
	CArr<int>      current_selected;
	MirrorList(hDlg, current_selected);

	for(i=0; i<set->section_count; i++)
	{
		if(item>= set->first_in_section[i]   &&
		   item<= set->last_in_section[i])
		   return true;
	}
	return false;
}
int  FindFirstDiff(CArr<int> &first, CArr<int> &second)
{
	int count,i;
	if( first.GetCount() != second.GetCount() )
		return 0;
	count = first.GetCount();
	for(i=0; i<count; i++)
		if(first[i]!=second[i])
			break;
	return i;
}

// helper function
void DlgSetText(HWND hDlg, int item, int number){
  
  char szTemp[1024];
  SetDlgItemText(hDlg, item, itoa(number, szTemp, 10));
}

LRESULT CALLBACK DlgSelector(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  int i,j, clicked_listitem, section, section_pos;
  CArr<int>  current_selected;
  
  switch (message)
  {
		case WM_INITDIALOG:	
      SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)set->tittle);

      SetDlgItemText(hDlg, R_RIGHT_SELECTOR_DIALOG, set->lateral_text);
      SetDlgItemText(hDlg, IDOK,  set->button_text);
      
      // Build the presentation list
      for(i=0; i<set->section_count; i++){
        SendDlgItemMessage(hDlg, IDC_SELECTOR, LB_ADDSTRING, 0, (LPARAM)set->sections_titles[i]);
        set->first_in_section[i] = 
          1 + SendDlgItemMessage(hDlg, IDC_SELECTOR, LB_ADDSTRING, 0, (LPARAM)"------------------------------------------------------------");
        
        for(j=0; j<set->strings[i].GetCount(); j++){
          set->last_in_section[i]=SendDlgItemMessage(hDlg, IDC_SELECTOR, LB_ADDSTRING, 0, (LPARAM)set->strings[i][j]);
        }
        SendDlgItemMessage(hDlg, IDC_SELECTOR, LB_ADDSTRING, 0, (LPARAM)"");
        //Select streams
      }
      RenderSelection(hDlg);
      // Now get a mirror image of the list box
      MirrorList(hDlg, listbox_mirror);
      return TRUE;
      
    case WM_COMMAND:
      if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
      {
        EndDialog(hDlg, LOWORD(wParam));
        return TRUE;
      }
      
      
      switch (LOWORD(wParam)) 
      { 
      case IDC_SELECTOR: 
        switch (HIWORD(wParam)) 
        { 
        case LBN_SELCHANGE: 
          // Guess if the item clicked belonged to a section
          MirrorList(hDlg, current_selected);
          clicked_listitem = FindFirstDiff(listbox_mirror, current_selected);
          if( ItemIsInSection(hDlg, clicked_listitem) )
          {
            // The item belongs to a section.
            // Guess section
            section      =    GetSection( hDlg, clicked_listitem );
            section_pos  = GetSectionPos( hDlg, clicked_listitem );
            
            // if SINGLE_SELECT
            if( set->section_mode[section]&SINGLE_SELECT )
            {
              int clicked_state = set->selected[section][section_pos];
              // Unselect all items in section
              for(i=0; i<set->strings[section].GetCount(); i++)
                set->selected[section][i] = 0;
              // select clicked item
              set->selected[section][section_pos] = !clicked_state;
            }
            if( set->section_mode[section]&MULTIPLE_SELECT )
            {
              set->selected[section][section_pos] = !set->selected[section][section_pos];
            }
            if( set->section_mode[section]&MUST_SELECT )
            {
              // if there are no selected items in this section
              if (GetSectionSelCount(hDlg, section) == 0)
                set->selected[section][section_pos] = 1;
            }
            
          }
          RenderSelection(hDlg);
          // Now get a mirror image of the list box
          MirrorList(hDlg, listbox_mirror);
          return TRUE; 
          
        } 
        break; 
        
        // Destroy the dialog box. 
        
        EndDialog(hDlg, TRUE); 
        return TRUE; 
        
        default: 
          return FALSE; 
      } 
      
      break;
  }
  return FALSE;
}

bool IsAnySelected( TSelectorDialog *set, int section )
{
  int i, nItems=set->strings[section].GetCount();
  for( i=0; i <nItems; i++ ){
    if( set->selected[section][i]==1 )
      break;
  }
  
  return i<nItems;  
}

int GetFirstSelected( TSelectorDialog *set, int section )
{
  int i;
  for( i=0; i <set->strings[section].GetCount(); i++ ){
    if( set->selected[section][i]==1 )
      break;
  }
  return i;
}
void ResetSelections(TSelectorDialog *set){
	int i,j;
	for(i=0; i<set->section_count; i++)
		set->selected[i].SetArraySize( set->strings[i].GetCount() );

	for(i=0; i<set->section_count; i++)
	{
		for(j=0; j<set->strings[i].GetCount(); j++)
			set->selected[i][j]=0;
	}
}

int OpenSelectorDialog(HWND hWnd, HINSTANCE hInstance, TSelectorDialog *settings){
	set = settings;
	return DialogBox(hInstance, (LPCTSTR)(IDD_STRSELECTOR), hWnd ,(DLGPROC)DlgSelector);
}
