/**
 * $Id$
 * Copyright (C) 2008 - 2014 Nils Asmussen
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <gui/layout/iconlayout.h>
#include <gui/application.h>
#include <gui/imagebutton.h>
#include <sys/common.h>
#include <sys/proc.h>
#include <stdio.h>

#include "desktopwin.h"

using namespace gui;
using namespace std;

const gsize_t DesktopWin::PADDING = 10;
const gsize_t DesktopWin::ICON_SIZE = 30;
const gsize_t DesktopWin::TASKBAR_HEIGHT = 24;

DesktopWin::DesktopWin(const Size &size,int childsm)
	: Window(Pos(0,0),size,DESKTOP), _childsm(childsm),
	  _winPanel(make_control<Panel>(Pos(0,0),Size(0,TASKBAR_HEIGHT),
			  	make_layout<FlowLayout>(FRONT,true,HORIZONTAL,4))),
	  _iconPanel(make_control<Background>(make_layout<IconLayout>(VERTICAL,PADDING))),
	  _active(nullptr), _windows(), _shortcuts() {
	auto root = getRootPanel();
	root->setLayout(make_layout<BorderLayout>());
	root->getTheme().setPadding(0);
	root->add(_winPanel,BorderLayout::SOUTH);
	root->add(_iconPanel,BorderLayout::CENTER);

	_iconPanel->getTheme().setColor(Theme::CTRL_BACKGROUND,Theme::DESKTOP_BG);

	Application *app = Application::getInstance();
	app->created().subscribe(mem_recv(this,&DesktopWin::onWindowCreated));
	app->activated().subscribe(mem_recv(this,&DesktopWin::onWindowActive));
	app->destroyed().subscribe(mem_recv(this,&DesktopWin::onWindowDestroyed));
}

void DesktopWin::onIconClick(UIElement& el) {
	auto it = std::find_if(_shortcuts.begin(),_shortcuts.end(),
		[&el] (const pair<std::shared_ptr<gui::ImageButton>,Shortcut*> &pair) {
			return &el == pair.first.get();
		}
	);
	if(it != _shortcuts.end()) {
		int pid = fork();
		if(pid == 0)
			execv(it->second->getArgs()[0],it->second->getArgs());
		else if(pid < 0)
			printe("Unable to create child-process");
		else
			semup(_childsm);
	}
}

void DesktopWin::onWinBtnClicked(UIElement& el) {
	for(auto wit = _windows.begin(); wit != _windows.end(); ++wit) {
		if((*wit).second.get() == &el) {
			Application::getInstance()->requestActiveWindow((*wit).first);
			break;
		}
	}
}

void DesktopWin::onWindowCreated(gwinid_t wid,const string& title) {
	auto b = make_control<WinButton>(this,title);
	_windows[wid] = b;
	_winPanel->add(b);
	_winPanel->layout();
	_winPanel->repaint();
}

void DesktopWin::onWindowActive(gwinid_t wid) {
	if(_active) {
		_active->getTheme().unsetColor(Theme::BTN_BACKGROUND);
		_active->repaint();
	}
	auto it = _windows.find(wid);
	if(it != _windows.end()) {
		_active = it->second.get();
		_active->getTheme().setColor(Theme::BTN_BACKGROUND,Theme::WIN_TITLE_ACT_BG);
		_active->repaint();
	}
	else
		_active = nullptr;
}

void DesktopWin::onWindowDestroyed(gwinid_t wid) {
	auto it = _windows.find(wid);
	if(it != _windows.end()) {
		shared_ptr<WinButton> b = (*it).second;
		_winPanel->remove(b);
		if(_active == b.get())
			_active = nullptr;
		_windows.erase(wid);
		_winPanel->layout();
		_winPanel->repaint();
	}
}
