void DialogSpellFailed(const Spell & spell)
{
    // failed
    std::string str = "%{spell} failed!!!";
    String::Replace(str, "%{spell}", spell.GetName());
    Dialog::Message("", str, Font::BIG, Dialog::OK);
}
void Dialog::SpellInfo(const Spell & spell, bool ok_button)
{
    std::string msg = spell.GetDescription();
    u32 extra = spell.ExtraValue();

    switch(spell())
    {
	case Spell::HASTE:
	case Spell::MASSHASTE:
	    if(0 == extra) extra = 2;
	    break;

	default: break;
    }

    if(1 == extra)
        StringReplace(msg, "%{count}", _("one"));
    else
    if(2 == extra)
        StringReplace(msg, "%{count}", _("two"));
    else
	StringReplace(msg, "%{count}", extra);

    Dialog::SpellInfo(spell.GetName(), msg, spell, ok_button);
}
bool Heroes::ActionSpellCast(const Spell & spell)
{
    std::string error;

    if(! CanMove())
    {
        Dialog::Message("", _("Your hero is too tired to cast this spell today. Try again tomorrow."), Font::BIG, Dialog::OK);
	return false;
    }
    else
    if(spell == Spell::NONE || spell.isCombat() || ! CanCastSpell(spell, &error))
    {
	if(error.size()) Dialog::Message("Error", error, Font::BIG, Dialog::OK);
	return false;
    }

    bool apply = false;

    switch(spell())
    {
	case Spell::VIEWMINES:		apply = ActionSpellViewMines(*this); break;
	case Spell::VIEWRESOURCES:	apply = ActionSpellViewResources(*this); break;
	case Spell::VIEWARTIFACTS:	apply = ActionSpellViewArtifacts(*this); break;
	case Spell::VIEWTOWNS:		apply = ActionSpellViewTowns(*this); break;
	case Spell::VIEWHEROES:		apply = ActionSpellViewHeroes(*this); break;
	case Spell::VIEWALL:		apply = ActionSpellViewAll(*this); break;
	case Spell::IDENTIFYHERO:	apply = ActionSpellIdentifyHero(*this); break;
	case Spell::SUMMONBOAT:		apply = ActionSpellSummonBoat(*this); break;
	case Spell::DIMENSIONDOOR:	apply = ActionSpellDimensionDoor(*this); break;
	case Spell::TOWNGATE:		apply = isShipMaster() ? false : ActionSpellTownGate(*this); break;
	case Spell::TOWNPORTAL:		apply = isShipMaster() ? false : ActionSpellTownPortal(*this); break;
	case Spell::VISIONS:		apply = ActionSpellVisions(*this); break;
	case Spell::HAUNT:		apply = ActionSpellSetGuardian(*this, spell, Monster::GHOST); break;
	case Spell::SETEGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::EARTH_ELEMENT); break;
	case Spell::SETAGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::AIR_ELEMENT); break;
	case Spell::SETFGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::FIRE_ELEMENT); break;
	case Spell::SETWGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::WATER_ELEMENT); break;
	default: break;
    }

    if(apply)
    {
	DEBUG(DBG_GAME, DBG_INFO, GetName() << " cast spell: " << spell.GetName());
	SpellCasted(spell);
	return true;
    }
    return false;
}
void Dialog::SpellInfo(const std::string &header, const std::string &message, const Spell & spell, bool ok_button)
{
    Display & display = Display::Get();
    const int system = Settings::Get().ExtGameEvilInterface() ? ICN::SYSTEME : ICN::SYSTEM;

    // cursor
    Cursor & cursor = Cursor::Get();

    cursor.Hide();
    cursor.SetThemes(cursor.POINTER);

    TextBox box1(header, Font::YELLOW_BIG, BOXAREA_WIDTH);
    TextBox box2(message, Font::BIG, BOXAREA_WIDTH);
    Text text(spell.GetName(), Font::SMALL);

    const Sprite & sprite = AGG::GetICN(ICN::SPELLS, spell.IndexSprite());
    const int spacer = Settings::Get().QVGA() ? 5 : 10;

    FrameBox box(box1.h() + spacer + box2.h() + spacer + sprite.h() + 2 + text.h(), ok_button);
    Rect pos = box.GetArea();

    if(header.size()) box1.Blit(pos);
    pos.y += box1.h() + spacer;

    if(message.size()) box2.Blit(pos);
    pos.y += box2.h() + spacer;

    // blit sprite
    pos.x = box.GetArea().x + (pos.w - sprite.w()) / 2;
    sprite.Blit(pos.x, pos.y);

    // small text
    pos.x = box.GetArea().x + (pos.w - text.w()) / 2;
    pos.y = pos.y + sprite.h() + 2;
    text.Blit(pos);

    LocalEvent & le = LocalEvent::Get();

    Button* button = NULL;
    Point pt;

    if(ok_button)
    {
        pt.x = box.GetArea().x + (box.GetArea().w - AGG::GetICN(system, 1).w()) / 2;
        pt.y = box.GetArea().y + box.GetArea().h - AGG::GetICN(system, 1).h();
	button = new Button(pt.x, pt.y, system, 1, 2);
    }

    if(button) (*button).Draw();

    cursor.Show();
    display.Flip();

    // message loop
    while(le.HandleEvents())
    {
        if(!ok_button && !le.MousePressRight()) break;
	if(button) le.MousePressLeft(*button) ? button->PressDraw() : button->ReleaseDraw();
        if(button && le.MouseClickLeft(*button)){ break; }
	if(HotKeyCloseWindow){ break; }
    }

    cursor.Hide();
    if(button) delete button;
}