/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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.
*/

use super::fp::FP;
use super::fp2::FP2;
use super::big::BIG;
use std::str::SplitWhitespace;

#[derive(Copy, Clone)]
pub struct FP4 {
    a: FP2,
    b: FP2,
}

impl PartialEq for FP4 {
	fn eq(&self, other: &FP4) -> bool {
		self.equals(other)
	}
}

impl FP4 {
    pub fn new() -> FP4 {
        FP4 {
            a: FP2::new(),
            b: FP2::new(),
        }
    }

    pub fn new_int(a: isize) -> FP4 {
        let mut f = FP4::new();
        f.a.copy(&FP2::new_int(a));
        f.b.zero();
        return f;
    }

    pub fn new_copy(x: &FP4) -> FP4 {
        let mut f = FP4::new();
        f.a.copy(&x.a);
        f.b.copy(&x.b);
        return f;
    }

    pub fn new_fp2s(c: &FP2, d: &FP2) -> FP4 {
        let mut f = FP4::new();
        f.a.copy(c);
        f.b.copy(d);
        return f;
    }

    pub fn new_fp2(c: &FP2) -> FP4 {
        let mut f = FP4::new();
        f.a.copy(c);
        f.b.zero();
        return f;
    }

    /* reduce components mod Modulus */
    pub fn reduce(&mut self) {
        self.a.reduce();
        self.b.reduce();
    }

    /* normalise components of w */
    pub fn norm(&mut self) {
        self.a.norm();
        self.b.norm();
    }

    pub fn cmove(&mut self, g: &FP4, d: isize) {
        self.a.cmove(&g.a, d);
        self.b.cmove(&g.b, d);
    }

    /* test self=0 ? */
    pub fn iszilch(&self) -> bool {
        return self.a.iszilch() && self.b.iszilch();
    }

    /* test self=1 ? */
    pub fn isunity(&self) -> bool {
        let one = FP2::new_int(1);
        return self.a.equals(&one) && self.b.iszilch();
    }

    /* test is w real? That is in a+ib test b is zero */
    pub fn isreal(&mut self) -> bool {
        return self.b.iszilch();
    }
    /* extract real part a */
    pub fn real(&self) -> FP2 {
        let f = FP2::new_copy(&self.a);
        return f;
    }

    pub fn geta(&self) -> FP2 {
        let f = FP2::new_copy(&self.a);
        return f;
    }
    /* extract imaginary part b */
    pub fn getb(&self) -> FP2 {
        let f = FP2::new_copy(&self.b);
        return f;
    }

    /* test self=x */
    pub fn equals(&self, x: &FP4) -> bool {
        return self.a.equals(&x.a) && self.b.equals(&x.b);
    }
    /* copy self=x */
    pub fn copy(&mut self, x: &FP4) {
        self.a.copy(&x.a);
        self.b.copy(&x.b);
    }

    /* set self=0 */
    pub fn zero(&mut self) {
        self.a.zero();
        self.b.zero();
    }

    /* set self=1 */
    pub fn one(&mut self) {
        self.a.one();
        self.b.zero();
    }

    /* negate self mod Modulus */
    pub fn neg(&mut self) {
        self.norm();
        let mut m = FP2::new_copy(&self.a);
        let mut t = FP2::new();

        m.add(&self.b);
        m.neg();
        t.copy(&m);
        t.add(&self.b);
        self.b.copy(&m);
        self.b.add(&self.a);
        self.a.copy(&t);
        self.norm();
    }

    /* set to a-ib */
    pub fn conj(&mut self) {
        self.b.neg();
        self.norm();
    }

    /* self=-conjugate(self) */
    pub fn nconj(&mut self) {
        self.a.neg();
        self.norm();
    }

    /* self+=a */
    pub fn add(&mut self, x: &FP4) {
        self.a.add(&x.a);
        self.b.add(&x.b);
    }

    pub fn padd(&mut self, x: &FP2) {
        self.a.add(x);
    }

    pub fn dbl(&mut self) {
        self.a.dbl();
        self.b.dbl();
    }

    /* self-=a */
    pub fn sub(&mut self, x: &FP4) {
        let mut m = FP4::new_copy(x);
        m.neg();
        self.add(&m);
    }

    /* self-=a */
    pub fn rsub(&mut self, x: &FP4) {
        self.neg();
        self.add(x);
    }

    /* self*=s, where s is an FP2 */
    pub fn pmul(&mut self, s: &FP2) {
        self.a.mul(s);
        self.b.mul(s);
    }

    /* self*=s, where s is an FP */
    pub fn qmul(&mut self, s: &FP) {
        self.a.pmul(s);
        self.b.pmul(s);
    }

    /* self*=i, where i is an int */
    pub fn imul(&mut self, c: isize) {
        self.a.imul(c);
        self.b.imul(c);
    }

    /* self*=self */

    pub fn sqr(&mut self) {
        let mut t1 = FP2::new_copy(&self.a);
        let mut t2 = FP2::new_copy(&self.b);
        let mut t3 = FP2::new_copy(&self.a);

        t3.mul(&self.b);
        t1.add(&self.b);
        t2.mul_ip();

        t2.add(&self.a);

        t1.norm();
        t2.norm();

        self.a.copy(&t1);

        self.a.mul(&t2);

        t2.copy(&t3);
        t2.mul_ip();
        t2.add(&t3);
        t2.norm();
        t2.neg();
        self.a.add(&t2);

        t3.dbl();
        self.b.copy(&t3);

        self.norm();
    }

    /* self*=y */
    pub fn mul(&mut self, y: &FP4) {
        //self.norm();

        let mut t1 = FP2::new_copy(&self.a);
        let mut t2 = FP2::new_copy(&self.b);
        let mut t3 = FP2::new();
        let mut t4 = FP2::new_copy(&self.b);

        t1.mul(&y.a);
        t2.mul(&y.b);
        t3.copy(&y.b);
        t3.add(&y.a);
        t4.add(&self.a);

        t3.norm();
        t4.norm();

        t4.mul(&t3);

        t3.copy(&t1);
        t3.neg();
        t4.add(&t3);
        t4.norm();

        t3.copy(&t2);
        t3.neg();
        self.b.copy(&t4);
        self.b.add(&t3);

        t2.mul_ip();
        self.a.copy(&t2);
        self.a.add(&t1);

        self.norm();
    }

    /* output to hex string */
    pub fn tostring(&mut self) -> String {
        return format!("[{},{}]", self.a.tostring(), self.b.tostring());
    }

    pub fn to_hex(&self) -> String {
        format!("{} {}", self.a.to_hex(), self.b.to_hex())
    }

    pub fn from_hex_iter(iter: &mut SplitWhitespace) -> FP4 {
        FP4 {
            a: FP2::from_hex_iter(iter),
            b: FP2::from_hex_iter(iter)
        }
    }

    pub fn from_hex(val: String) -> FP4 {
        let mut iter = val.split_whitespace();
        return FP4::from_hex_iter(&mut iter);
    }

    /* self=1/self */
    pub fn inverse(&mut self) {
        //self.norm();

        let mut t1 = FP2::new_copy(&self.a);
        let mut t2 = FP2::new_copy(&self.b);

        t1.sqr();
        t2.sqr();
        t2.mul_ip();
        t2.norm();
        t1.sub(&t2);
        t1.inverse();
        self.a.mul(&t1);
        t1.neg();
        t1.norm();
        self.b.mul(&t1);
    }

    /* self*=i where i = sqrt(-1+sqrt(-1)) */
    pub fn times_i(&mut self) {
        let mut s = FP2::new_copy(&self.b);
        let mut t = FP2::new_copy(&self.b);
        s.times_i();
        t.add(&s);
        self.b.copy(&self.a);
        self.a.copy(&t);
        self.norm();
    }

    /* self=self^p using Frobenius */
    pub fn frob(&mut self, f: &FP2) {
        self.a.conj();
        self.b.conj();
        self.b.mul(f);
    }

    /* self=self^e */
    pub fn pow(&self, e: &BIG) -> FP4 {
        let mut w = FP4::new_copy(self);
        w.norm();
        let mut z = BIG::new_copy(&e);
        let mut r = FP4::new_int(1);
        z.norm();
        loop {
            let bt = z.parity();
            z.fshr(1);
            if bt == 1 {
                r.mul(&mut w)
            };
            if z.iszilch() {
                break;
            }
            w.sqr();
        }
        r.reduce();
        return r;
    }

    /* XTR xtr_a function */
    pub fn xtr_a(&mut self, w: &FP4, y: &FP4, z: &FP4) {
        let mut r = FP4::new_copy(w);
        let mut t = FP4::new_copy(w);
        r.sub(y);
        r.norm();
        r.pmul(&self.a);
        t.add(y);
        t.norm();
        t.pmul(&self.b);
        t.times_i();

        self.copy(&r);
        self.add(&t);
        self.add(z);

        self.norm();
    }

    /* XTR xtr_d function */
    pub fn xtr_d(&mut self) {
        let mut w = FP4::new_copy(self);
        self.sqr();
        w.conj();
        w.dbl();
        w.norm();
        self.sub(&w);
        self.reduce();
    }

    /* r=x^n using XTR method on traces of FP12s */
    pub fn xtr_pow(&self, n: &BIG) -> FP4 {
        let mut sf = FP4::new_copy(self);
        sf.norm();
        let mut a = FP4::new_int(3);
        let mut b = FP4::new_copy(&sf);
        let mut c = FP4::new_copy(&b);
        c.xtr_d();
        let mut t = FP4::new();
        let mut r = FP4::new();

        let par = n.parity();
        let mut v = BIG::new_copy(n);
        v.norm();
        v.fshr(1);
        if par == 0 {
            v.dec(1);
            v.norm();
        }

        let nb = v.nbits();
        for i in (0..nb).rev() {
            if v.bit(i) != 1 {
                t.copy(&b);
                sf.conj();
                c.conj();
                b.xtr_a(&a, &sf, &c);
                sf.conj();
                c.copy(&t);
                c.xtr_d();
                a.xtr_d();
            } else {
                t.copy(&a);
                t.conj();
                a.copy(&b);
                a.xtr_d();
                b.xtr_a(&c, &sf, &t);
                c.xtr_d();
            }
        }
        if par == 0 {
            r.copy(&c)
        } else {
            r.copy(&b)
        }
        r.reduce();
        return r;
    }

    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
    pub fn xtr_pow2(&mut self, ck: &FP4, ckml: &FP4, ckm2l: &FP4, a: &BIG, b: &BIG) -> FP4 {
        let mut e = BIG::new_copy(a);
        let mut d = BIG::new_copy(b);
        let mut w = BIG::new();
        e.norm();
        d.norm();

        let mut cu = FP4::new_copy(ck); // can probably be passed in w/o copying
        let mut cv = FP4::new_copy(self);
        let mut cumv = FP4::new_copy(ckml);
        let mut cum2v = FP4::new_copy(ckm2l);
        let mut r = FP4::new();
        let mut t = FP4::new();

        let mut f2: usize = 0;
        while d.parity() == 0 && e.parity() == 0 {
            d.fshr(1);
            e.fshr(1);
            f2 += 1;
        }

        while BIG::comp(&d, &e) != 0 {
            if BIG::comp(&d, &e) > 0 {
                w.copy(&e);
                w.imul(4);
                w.norm();
                if BIG::comp(&d, &w) <= 0 {
                    w.copy(&d);
                    d.copy(&e);
                    e.rsub(&w);
                    e.norm();

                    t.copy(&cv);
                    t.xtr_a(&cu, &cumv, &cum2v);
                    cum2v.copy(&cumv);
                    cum2v.conj();
                    cumv.copy(&cv);
                    cv.copy(&cu);
                    cu.copy(&t);
                } else {
                    if d.parity() == 0 {
                        d.fshr(1);
                        r.copy(&cum2v);
                        r.conj();
                        t.copy(&cumv);
                        t.xtr_a(&cu, &cv, &r);
                        cum2v.copy(&cumv);
                        cum2v.xtr_d();
                        cumv.copy(&t);
                        cu.xtr_d();
                    } else {
                        if e.parity() == 1 {
                            d.sub(&e);
                            d.norm();
                            d.fshr(1);
                            t.copy(&cv);
                            t.xtr_a(&cu, &cumv, &cum2v);
                            cu.xtr_d();
                            cum2v.copy(&cv);
                            cum2v.xtr_d();
                            cum2v.conj();
                            cv.copy(&t);
                        } else {
                            w.copy(&d);
                            d.copy(&e);
                            d.fshr(1);
                            e.copy(&w);
                            t.copy(&cumv);
                            t.xtr_d();
                            cumv.copy(&cum2v);
                            cumv.conj();
                            cum2v.copy(&t);
                            cum2v.conj();
                            t.copy(&cv);
                            t.xtr_d();
                            cv.copy(&cu);
                            cu.copy(&t);
                        }
                    }
                }
            }
            if BIG::comp(&d, &e) < 0 {
                w.copy(&d);
                w.imul(4);
                w.norm();
                if BIG::comp(&e, &w) <= 0 {
                    e.sub(&d);
                    e.norm();
                    t.copy(&cv);
                    t.xtr_a(&cu, &cumv, &cum2v);
                    cum2v.copy(&cumv);
                    cumv.copy(&cu);
                    cu.copy(&t);
                } else {
                    if e.parity() == 0 {
                        w.copy(&d);
                        d.copy(&e);
                        d.fshr(1);
                        e.copy(&w);
                        t.copy(&cumv);
                        t.xtr_d();
                        cumv.copy(&cum2v);
                        cumv.conj();
                        cum2v.copy(&t);
                        cum2v.conj();
                        t.copy(&cv);
                        t.xtr_d();
                        cv.copy(&cu);
                        cu.copy(&t);
                    } else {
                        if d.parity() == 1 {
                            w.copy(&e);
                            e.copy(&d);
                            w.sub(&d);
                            w.norm();
                            d.copy(&w);
                            d.fshr(1);
                            t.copy(&cv);
                            t.xtr_a(&cu, &cumv, &cum2v);
                            cumv.conj();
                            cum2v.copy(&cu);
                            cum2v.xtr_d();
                            cum2v.conj();
                            cu.copy(&cv);
                            cu.xtr_d();
                            cv.copy(&t);
                        } else {
                            d.fshr(1);
                            r.copy(&cum2v);
                            r.conj();
                            t.copy(&cumv);
                            t.xtr_a(&cu, &cv, &r);
                            cum2v.copy(&cumv);
                            cum2v.xtr_d();
                            cumv.copy(&t);
                            cu.xtr_d();
                        }
                    }
                }
            }
        }
        r.copy(&cv);
        r.xtr_a(&cu, &cumv, &cum2v);
        for _ in 0..f2 {
            r.xtr_d()
        }
        r = r.xtr_pow(&mut d);
        return r;
    }

    /* this/=2 */
    pub fn div2(&mut self) {
        self.a.div2();
        self.b.div2();
    }

    pub fn div_i(&mut self) {
        let mut u = FP2::new_copy(&self.a);
        let v = FP2::new_copy(&self.b);
        u.div_ip();
        self.a.copy(&v);
        self.b.copy(&u);
    }

    pub fn div_2i(&mut self) {
        let mut u = FP2::new_copy(&self.a);
        let mut v = FP2::new_copy(&self.b);
        u.div_ip2();
        v.dbl();
        v.norm();
        self.a.copy(&v);
        self.b.copy(&u);
    }

    /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
    /* returns true if this is QR */
    pub fn sqrt(&mut self) -> bool {
        if self.iszilch() {
            return true;
        }

        let mut a = FP2::new_copy(&self.a);
        let mut s = FP2::new_copy(&self.b);
        let mut t = FP2::new_copy(&self.a);

        if s.iszilch() {
            if t.sqrt() {
                self.a.copy(&t);
                self.b.zero();
            } else {
                t.div_ip();
                t.sqrt();
                self.b.copy(&t);
                self.a.zero();
            }
            return true;
        }
        s.sqr();
        a.sqr();
        s.mul_ip();
        s.norm();
        a.sub(&s);

        s.copy(&a);
        if !s.sqrt() {
            return false;
        }

        a.copy(&t);
        a.add(&s);
        a.norm();
        a.div2();

        if !a.sqrt() {
            a.copy(&t);
            a.sub(&s);
            a.norm();
            a.div2();
            if !a.sqrt() {
                return false;
            }
        }
        t.copy(&self.b);
        s.copy(&a);
        s.add(&a);
        s.inverse();

        t.mul(&s);
        self.a.copy(&a);
        self.b.copy(&t);

        return true;
    }
}
