package com.planet_ink.coffee_mud.Items.BasicTech;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.Armor.SizeDeviation;
import com.planet_ink.coffee_mud.Items.interfaces.Technical.TechType;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;

/*
   Copyright 2013-2022 Bo Zimmerman

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
public class StdPersonalShield extends StdElecItem implements Armor
{
	@Override
	public String ID()
	{
		return "StdPersonalShield";
	}

	short layer=0;
	short layerAttributes=0;

	public StdPersonalShield()
	{
		super();
		setName("a personal shield generator");
		basePhyStats.setWeight(2);
		setDisplayText("a personal shield generator sits here.");
		setDescription("The muting field generator is worn about the body and activated to use. It neutralizes weapon damage. ");
		baseGoldValue=2500;
		basePhyStats().setLevel(1);
		recoverPhyStats();
		setMaterial(RawMaterial.RESOURCE_STEEL);
		super.activate(true);
		super.setRawProperLocationBitmap(Wearable.WORN_ABOUT_BODY);
		super.setPowerCapacity(1000);
		super.setPowerRemaining(1000);
	}

	protected String fieldOnStr(final MOB viewerM)
	{
		return L((owner() instanceof MOB)?
			"A field of energy surrounds <O-NAME>.":
			"A field of energy surrounds <T-NAME>.");
	}

	protected String fieldDeadStr(final MOB viewerM)
	{
		return L((owner() instanceof MOB)?"" +
			"The field around <O-NAME> flickers and dies out.":
			"The field around <T-NAME> flickers and dies out.");
	}

	@Override
	public TechType getTechType()
	{
		return TechType.PERSONAL_SHIELD;
	}

	protected boolean doShield(final MOB mob, final CMMsg msg, final double successFactor)
	{
		if(mob.location()!=null)
		{
			if(msg.tool() instanceof Weapon)
			{
				final String s="^F"+((Weapon)msg.tool()).hitString(0)+"^N";
				if(s.indexOf("<DAMAGE> <T-HIM-HER>")>0)
					mob.location().show(msg.source(),msg.target(),msg.tool(),CMMsg.MSG_OK_VISUAL,CMStrings.replaceAll(s, "<DAMAGE>", L("it reflects off the shield around")));
				else
				if(s.indexOf("<DAMAGES> <T-HIM-HER>")>0)
					mob.location().show(msg.source(),msg.target(),msg.tool(),CMMsg.MSG_OK_VISUAL,CMStrings.replaceAll(s, "<DAMAGES>", L("reflects off the shield around")));
				else
					mob.location().show(mob,msg.source(),msg.tool(),CMMsg.MSG_OK_VISUAL,L("The field around <S-NAME> reflects the <O-NAMENOART> damage."));
			}
			else
				mob.location().show(mob,msg.source(),msg.tool(),CMMsg.MSG_OK_VISUAL,L("The field around <S-NAME> reflects the <O-NAMENOART> damage."));
		}
		return false;
	}

	protected boolean doesShield(final MOB mob, final CMMsg msg, final double successFactor)
	{
		return (Math.random() >= successFactor) && activated();
	}

	@Override
	public boolean sameAs(final Environmental E)
	{
		if(!(E instanceof StdPersonalShield))
			return false;
		return super.sameAs(E);
	}

	@Override
	public void setMiscText(final String newText)
	{
		if(CMath.isInteger(newText))
			this.setPowerCapacity(CMath.s_int(newText));
		super.setMiscText(newText);
	}

	@Override
	public SizeDeviation getSizingDeviation(final MOB mob)
	{
		return SizeDeviation.FITS;
	}

	@Override
	public boolean okMessage(final Environmental myHost, final CMMsg msg)
	{
		if(!super.okMessage(myHost, msg))
			return false;
		if(msg.amITarget(owner()) && (owner() instanceof MOB))
		{
			final MOB mob=(MOB)owner();
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_REMOVE:
			case CMMsg.TYP_DROP:
				if(activated())
					msg.addTrailerMsg(CMClass.getMsg(mob, this, null,CMMsg.MSG_OK_VISUAL,CMMsg.TYP_DEACTIVATE|CMMsg.MASK_ALWAYS,CMMsg.MSG_OK_VISUAL,fieldDeadStr(msg.source())));
				break;
			case CMMsg.TYP_DAMAGE: // remember 50% miss rate
				if((activated())
				&&(powerRemaining()>0)
				&& amBeingWornProperly())
				{
					double successFactor=0.5;
					final Manufacturer m=getFinalManufacturer();
					successFactor=m.getReliabilityPct()*successFactor;
					int weaponTech=CMLib.tech().getGlobalTechLevel();
					if(msg.tool() instanceof Electronics)
						weaponTech=((Electronics)msg.tool()).techLevel();
					final int myTech=techLevel();
					final int techDiff=Math.max(Math.min(myTech-weaponTech,10),-10);
					if(techDiff!= 0)
						successFactor+=(0.05)*techDiff;
					if(doesShield(mob, msg, successFactor))
					{
						final long powerConsumed=Math.round(msg.value()*Math.max(.33, Math.abs(2.0-m.getEfficiencyPct())));
						if(powerRemaining()>=powerConsumed)
						{
							setPowerRemaining(powerRemaining()-powerConsumed);
							if(!doShield(mob,msg, successFactor))
								return false;
						}
						else
							setPowerRemaining(0);
					}
					if(powerRemaining()<=0)
					{
						setPowerRemaining(0);
						final CMMsg msg2=CMClass.getMsg(mob, this, null,CMMsg.MSG_OK_VISUAL,CMMsg.TYP_DEACTIVATE|CMMsg.MASK_ALWAYS,CMMsg.MSG_OK_VISUAL,fieldDeadStr(msg.source()));
						if(mob.location()!=null)
							mob.location().send(mob, msg2);
					}
				}
				break;
			}
		}
		return true;
	}

	@Override
	public void executeMsg(final Environmental host, final CMMsg msg)
	{
		if(msg.amITarget(this))
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_LOOK:
			case CMMsg.TYP_EXAMINE:
				super.executeMsg(host, msg);
				if(CMLib.flags().canBeSeenBy(this, msg.source()))
					msg.source().tell(L("@x1 is currently @x2 and is at @x3% power.",name(),(activated()?"activated":"deactivated"),""+Math.round(CMath.div(powerRemaining(),powerCapacity())*100.0)));
				return;
			case CMMsg.TYP_ACTIVATE:
			{
				if((msg.source().location()!=null)&&(!CMath.bset(msg.targetMajor(), CMMsg.MASK_CNTRLMSG)))
					msg.source().location().show(msg.source(), this, owner(), CMMsg.MSG_OK_VISUAL, fieldOnStr(null));
				this.activate(true);
				final Physical P=owner();
				if(P!=null)
				{
					P.recoverPhyStats();
					if(P instanceof MOB)
					{
						((MOB)P).recoverCharStats();
						((MOB)P).recoverMaxState();
					}
				}
				break;
			}
			case CMMsg.TYP_DEACTIVATE:
			{
				if((msg.source().location()!=null)&&(!CMath.bset(msg.targetMajor(), CMMsg.MASK_CNTRLMSG)))
					msg.source().location().show(msg.source(), this, owner(), CMMsg.MSG_OK_VISUAL, fieldDeadStr(null));
				this.activate(false);
				final Physical P=owner();
				if(P!=null)
				{
					P.recoverPhyStats();
					if(P instanceof MOB)
					{
						((MOB)P).recoverCharStats();
						((MOB)P).recoverMaxState();
					}
				}
				break;
			}
			default:
				super.executeMsg(host,msg);
				break;
			}
		}
		else
		if(msg.amITarget(owner())
		&& (owner() instanceof MOB)
		&& (!amWearingAt(Wearable.IN_INVENTORY)))
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_LOOK:
				super.executeMsg(host, msg);
				if(CMLib.flags().canBeSeenBy(owner(), msg.source()) &&(activated())&&(powerRemaining()>0))
					msg.source().tell(msg.source(),this,owner(),fieldOnStr(msg.source()));
				return;
			}
		}
		super.executeMsg(host, msg);
	}

	@Override
	public short getClothingLayer()
	{
		return layer;
	}

	@Override
	public void setClothingLayer(final short newLayer)
	{
		layer = newLayer;
	}

	@Override
	public short getLayerAttributes()
	{
		return layerAttributes;
	}

	@Override
	public void setLayerAttributes(final short newAttributes)
	{
		layerAttributes = newAttributes;
	}

	@Override
	public boolean canWear(final MOB mob, final long where)
	{
		if(where==0)
			return (whereCantWear(mob)==0);
		if((rawProperLocationBitmap()&where)!=where)
			return false;
		return mob.freeWearPositions(where,getClothingLayer(),getLayerAttributes())>0;
	}

}
