"""

Compute surface and Volume of the astrocyte

"""


import numpy as np
from dolfin import *
from cutfem import *
parameters["form_compiler"]["no-evaluate_basis_derivatives"] = False
parameters['allow_extrapolation'] = True


def compute_area(bg_mesh, level_set, subdom2comp):

    # Create mesh
    mesh = CutFEMTools_fictitious_domain_mesh(bg_mesh, level_set, 0, 0)

    # Compute Mesh -Levelset intersection and corresponding marker
    mesh_cutter = MeshCutter(mesh, level_set)

    # Define new measures associated with the interior domains and facets
    dx = Measure("dx", domain=mesh)[mesh_cutter.domain_marker()]
    dxq = dc(0, metadata={"num_cells": 1})  # cut cells inside the Circle

    dxc = dx(0) + dxq

    V0 = FunctionSpace(mesh, "Lagrange", 1)

    # Fictitious domain
    composite_mesh = CompositeMesh()
    composite_mesh.add(mesh)

    V = CompositeFunctionSpace(composite_mesh)
    V.add(V0);
    V.build();

    # Constrain dofs outside
    FidoTools_compute_constrained_dofs(V, mesh_cutter)

    u_e_V0 = project(subdom2comp, V0)

    psi0 = u_e_V0 * dxc

    form_psi0 = create_dolfin_form(psi0)

    composite_form_psi0 = CompositeForm(V)
    composite_form_psi0.add(form_psi0)

    cut_cells = mesh_cutter.cut_cells(0)

    quadrature = Quadrature(cut_cells.type().cell_type(),
                            cut_cells.geometry().dim(),
                            order=2)

    composite_form_psi0.cut_form(0).set_quadrature(0, quadrature);
    composite_form_psi0.cut_form(0).set_cut_mesh(0, cut_cells);
    composite_form_psi0.cut_form(0).add_single_parent_mesh_id(0, 0);

    area_ls_cutfem = composite_assemble(composite_form_psi0)

    return(area_ls_cutfem)



def compute_surface(bg_mesh, level_set):

    # Create mesh
    mesh = CutFEMTools_surface_band_mesh(bg_mesh, level_set)

    # Compute Mesh -Levelset intersection and corresponding marker
    mesh_cutter = MeshCutter(mesh, level_set)

    # Compute Mesh -Levelset intersection and corresponding marker
    mesh_cutter = MeshCutter(mesh, level_set)
    # Define new measures associated with the interior domains and facets
    dsq = dc(0, metadata={"num_cells": 1})

    V0 = FunctionSpace(mesh, "Lagrange", 1)

    # Fictitious domain
    composite_mesh = CompositeMesh()
    composite_mesh.add(mesh)

    V = CompositeFunctionSpace(composite_mesh)
    V.add(V0);
    V.build();

    # Constrain dofs outside
    FidoTools_compute_constrained_dofs(V, mesh_cutter)

    u_e_V0 = project(Constant(1.), V0)

    psi0 = u_e_V0 * dsq

    form_psi0 = create_dolfin_form(psi0)

    composite_form_psi0 = SurfaceForm(V)
    composite_form_psi0.add(form_psi0, mesh_cutter)

    surf_ls_cutfem = composite_assemble(composite_form_psi0)

    return(surf_ls_cutfem)