package edx.electrical.circuit.component.laser

import cpw.mods.fml.client.FMLClientHandler
import cpw.mods.fml.relauncher.{Side, SideOnly}
import edx.core.Reference
import edx.electrical.Models
import net.minecraft.block.BlockPistonBase
import net.minecraft.block.material.Material
import net.minecraft.entity.EntityLivingBase
import net.minecraft.item.ItemStack
import net.minecraft.util.{MovingObjectPosition, ResourceLocation}
import net.minecraft.world.IBlockAccess
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11._
import resonantengine.lib.grid.energy.electric.NodeElectricComponent
import resonantengine.lib.modcontent.block.ResonantTile
import resonantengine.lib.render.RenderUtility
import resonantengine.lib.transform.vector.Vector3
import resonantengine.prefab.block.impl.{TBlockNodeProvider, TRotatable}

import scala.collection.convert.wrapAll._

/**
 * A block that receives laser light and generates a voltage.
 * @author Calclavia
 */
object TileLaserReceiver
{
  val texture = new ResourceLocation(Reference.domain, Reference.modelPath + "laserReceiver.png")
}

class TileLaserReceiver extends ResonantTile(Material.rock) with ILaserHandler with TBlockNodeProvider with TRotatable
{
  val electricNode = new NodeElectricComponent(this)

  private var energy = 0D

  var redstoneValue = 0
  private var prevRedstoneValue = 0;

  domain = ""
  textureName = "stone"
  normalRender = false
  isOpaqueCube = false
  nodes.add(electricNode)
  providePower = true

  electricNode.dynamicTerminals = true
  electricNode.setPositives(Set(ForgeDirection.NORTH, ForgeDirection.EAST))
  electricNode.setNegatives(Set(ForgeDirection.SOUTH, ForgeDirection.WEST))

  override def canUpdate: Boolean = true

  override def onLaserHit(renderStart: Vector3, incident: Vector3, hit: MovingObjectPosition, color: Vector3, energy: Double): Boolean =
  {
    if (hit.sideHit == getDirection.ordinal)
    {
      this.energy += energy
      electricNode.generatePower(energy)
    }

    return false
  }

  override def onPlaced(entityLiving: EntityLivingBase, itemStack: ItemStack)
  {
    val l = BlockPistonBase.determineOrientation(world, x.toInt, y.toInt, z.toInt, entityLiving)
    world.setBlockMetadataWithNotify(x.toInt, y.toInt, z.toInt, l, 2)
  }

  @SideOnly(Side.CLIENT)
  override def renderDynamic(pos: Vector3, frame: Float, pass: Int)
  {
    glPushMatrix()
    glTranslated(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5)

    RenderUtility.enableBlending()

    getDirection match
    {
      case ForgeDirection.UNKNOWN =>
      case ForgeDirection.UP => glRotatef(-90, 1, 0, 0)
      case ForgeDirection.DOWN => glRotatef(90, 1, 0, 0)
      case ForgeDirection.NORTH => glRotatef(90, 0, 1, 0)
      case ForgeDirection.SOUTH => glRotatef(-90, 0, 1, 0)
      case ForgeDirection.WEST => glRotatef(-180, 0, 1, 0)
      case ForgeDirection.EAST => glRotatef(0, 0, 1, 0)
    }

    if (getDirection.offsetY == 0)
      glRotatef(-90, 0, 1, 0)
    else
      glRotatef(180, 1, 0, 0)

    FMLClientHandler.instance.getClient.renderEngine.bindTexture(TileLaserReceiver.texture)
    Models.laserreceiver.renderAll()

    RenderUtility.disableBlending()

    glPopMatrix()
  }

  @SideOnly(Side.CLIENT)
  override def renderInventory(itemStack: ItemStack)
  {
    glPushMatrix()
    glRotated(180, 0, 1, 0)

    RenderUtility.enableBlending()

    FMLClientHandler.instance.getClient.renderEngine.bindTexture(TileLaserReceiver.texture)
    Models.laserreceiver.renderAll()

    RenderUtility.disableBlending()

    glPopMatrix()
  }

  override def update()
  {
    super.update()
    if (energy > 0)
    {
      redstoneValue = Math.min(Math.ceil(energy / (Laser.maxEnergy / 15)), 15).toInt

      if (redstoneValue != prevRedstoneValue)
      {
        world.notifyBlocksOfNeighborChange(x.toInt, y.toInt, z.toInt, getBlockType)
        ForgeDirection.VALID_DIRECTIONS.foreach(dir => world.notifyBlocksOfNeighborChange(x.toInt + dir.offsetX, y.toInt + dir.offsetY, z.toInt + dir.offsetZ, getBlockType))
        prevRedstoneValue = redstoneValue
      }

      energy = 0
    }
    else
    {
      redstoneValue = 0

      if (redstoneValue != prevRedstoneValue)
      {
        world.notifyBlocksOfNeighborChange(x.toInt, y.toInt, z.toInt, getBlockType)
        ForgeDirection.VALID_DIRECTIONS.foreach(dir => world.notifyBlocksOfNeighborChange(x.toInt + dir.offsetX, y.toInt + dir.offsetY, z.toInt + dir.offsetZ, getBlockType))
        prevRedstoneValue = redstoneValue
      }
    }
  }

  override def getWeakRedstonePower(access: IBlockAccess, side: Int): Int = redstoneValue
}
