use std::marker::PhantomData;
use std::fmt;
use std::ptr;
use std::mem;
use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr};
use context::Context;
use object::{ToObject, Object};
use object;
use types::Type;
use types;
use field::Field;
use field;
use lvalue::LValue;
use lvalue;
use location::Location;
use location;
use block::BinaryOp;

/// An RValue is a value that may or may not have a storage address in gccjit.
/// RValues can be dereferenced, used for field accesses, and are the parameters
/// given to a majority of the gccjit API calls.
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
pub struct RValue<'ctx> {
    marker: PhantomData<&'ctx Context<'ctx>>,
    ptr: *mut gccjit_sys::gcc_jit_rvalue
}

/// ToRValue is a trait implemented by types that can be converted to, or
/// treated as, an RValue.
pub trait ToRValue<'ctx> {
    fn to_rvalue(&self) -> RValue<'ctx>;
}

impl<'ctx> ToObject<'ctx> for RValue<'ctx> {
    fn to_object(&self) -> Object<'ctx> {
        unsafe {
            object::from_ptr(gccjit_sys::gcc_jit_rvalue_as_object(self.ptr))
        }
    }
}

impl<'ctx> fmt::Debug for RValue<'ctx> {
    fn fmt<'a>(&self, fmt: &mut fmt::Formatter<'a>) -> Result<(), fmt::Error> {
        let obj = self.to_object();
        obj.fmt(fmt)
    }
}

impl<'ctx> ToRValue<'ctx> for RValue<'ctx> {
    fn to_rvalue(&self) -> RValue<'ctx> {
        unsafe { from_ptr(self.ptr) }
    }
}

macro_rules! binary_operator_for {
    ($ty:ty, $name:ident, $op:expr) => {
        impl<'ctx> $ty for RValue<'ctx> {
            type Output = RValue<'ctx>;

            fn $name(self, rhs: RValue<'ctx>) -> RValue<'ctx> {
                unsafe {
                    let rhs_rvalue = rhs.to_rvalue();
                    let obj_ptr = object::get_ptr(&self.to_object());
                    let ctx_ptr = gccjit_sys::gcc_jit_object_get_context(obj_ptr);
                    let ty = rhs.get_type();
                    let ptr = gccjit_sys::gcc_jit_context_new_binary_op(ctx_ptr,
                        ptr::null_mut(),
                        mem::transmute::<BinaryOp, gccjit_sys::gcc_jit_binary_op>($op),
                        types::get_ptr(&ty),
                        self.ptr,
                        rhs_rvalue.ptr);
                    #[cfg(debug_assertions)]
                    if let Ok(Some(error)) = self.to_object().get_context().get_last_error() {
                        panic!("{}", error);
                    }
                    from_ptr(ptr)
                }
            }
        }
    }
}

// Operator overloads for ease of manipulation of rvalues
binary_operator_for!(Add, add, BinaryOp::Plus);
binary_operator_for!(Sub, sub, BinaryOp::Minus);
binary_operator_for!(Mul, mul, BinaryOp::Mult);
binary_operator_for!(Div, div, BinaryOp::Divide);
binary_operator_for!(Rem, rem, BinaryOp::Modulo);
binary_operator_for!(BitAnd, bitand, BinaryOp::BitwiseAnd);
binary_operator_for!(BitOr, bitor, BinaryOp::BitwiseOr);
binary_operator_for!(BitXor, bitxor, BinaryOp::BitwiseXor);
binary_operator_for!(Shl<RValue<'ctx>>, shl, BinaryOp::LShift);
binary_operator_for!(Shr<RValue<'ctx>>, shr, BinaryOp::RShift);

impl<'ctx> RValue<'ctx> {
    /// Gets the type of this RValue.
    pub fn get_type(&self) -> Type<'ctx> {
        unsafe {
            let ptr = gccjit_sys::gcc_jit_rvalue_get_type(self.ptr);
            types::from_ptr(ptr)
        }
    }

    /// Sets the location of this RValue.
    #[cfg(feature="master")]
    pub fn set_location(&self, loc: Location) {
        unsafe {
            let loc_ptr = location::get_ptr(&loc);
            gccjit_sys::gcc_jit_rvalue_set_location(self.ptr, loc_ptr);
        }
    }

    /// Change the type of this RValue.
    #[cfg(feature="master")]
    pub fn set_type(&self, typ: Type<'ctx>) {
        unsafe {
            let type_ptr = types::get_ptr(&typ);
            gccjit_sys::gcc_jit_rvalue_set_type(self.ptr, type_ptr);
        }
    }

    /// Given an RValue x and a Field f, returns an RValue representing
    /// C's x.f.
    pub fn access_field(&self,
                        loc: Option<Location<'ctx>>,
                        field: Field<'ctx>) -> RValue<'ctx> {
        let loc_ptr = match loc {
            Some(loc) => unsafe { location::get_ptr(&loc) },
            None => ptr::null_mut()
        };
        unsafe {
            let ptr = gccjit_sys::gcc_jit_rvalue_access_field(self.ptr,
                                                              loc_ptr,
                                                              field::get_ptr(&field));
            from_ptr(ptr)
        }
    }

    /// Given an RValue x and a Field f, returns an LValue representing
    /// C's x->f.
    pub fn dereference_field(&self,
                             loc: Option<Location<'ctx>>,
                             field: Field<'ctx>) -> LValue<'ctx> {
        let loc_ptr = match loc {
            Some(loc) => unsafe { location::get_ptr(&loc) },
            None => ptr::null_mut()
        };
        unsafe {
            let ptr = gccjit_sys::gcc_jit_rvalue_dereference_field(self.ptr,
                                                                   loc_ptr,
                                                                   field::get_ptr(&field));
            #[cfg(debug_assertions)]
            if let Ok(Some(error)) = self.to_object().get_context().get_last_error() {
                panic!("{}", error);
            }
            lvalue::from_ptr(ptr)
        }
    }

    /// Given a RValue x, returns an RValue that represents *x.
    pub fn dereference(&self,
                       loc: Option<Location<'ctx>>) -> LValue<'ctx> {
        let loc_ptr = match loc {
            Some(loc) => unsafe { location::get_ptr(&loc) },
            None => ptr::null_mut()
        };
        unsafe {
            let ptr = gccjit_sys::gcc_jit_rvalue_dereference(self.ptr,
                                                             loc_ptr);

            #[cfg(debug_assertions)]
            if let Ok(Some(error)) = self.to_object().get_context().get_last_error() {
                panic!("{}", error);
            }
            lvalue::from_ptr(ptr)
        }
    }
}

pub unsafe fn from_ptr<'ctx>(ptr: *mut gccjit_sys::gcc_jit_rvalue) -> RValue<'ctx> {
    RValue {
        marker: PhantomData,
        ptr
    }
}

pub unsafe fn get_ptr<'ctx>(rvalue: &RValue<'ctx>) -> *mut gccjit_sys::gcc_jit_rvalue {
    rvalue.ptr
}
