from __future__ import division, with_statement

from ...._common import block_to_format, get_label_length, open_file
from ...._exceptions import ReadError
from ...._helpers import FileIterator
from ._helpers import prune_nones_dict, prune_nones_list, read_record

__all__ = [
    "read",
]


oft_to_key = {
    "FOFT": "element_history",
    "COFT": "connection_history",
    "GOFT": "generator_history",
}


def read(filename, label_length=None, eos=None):
    """
    Read TOUGH input file.

    Parameters
    ----------
    filename : str
        Input file name.
    label_length : int or None, optional, default None
        Number of characters in cell labels.
    eos : str or None, optional, default None
        Equation of State.

    Returns
    -------
    dict
        TOUGH input parameters.

    """
    if not (label_length is None or isinstance(label_length, int)):
        raise TypeError()
    if isinstance(label_length, int) and not 5 <= label_length < 10:
        raise ValueError()

    with open_file(filename, "r") as f:
        out = read_buffer(f, label_length, eos)

    return out


def read_buffer(f, label_length, eos):
    """Read TOUGH input file."""
    from ._common import blocks

    parameters = {}

    # Title
    title = []
    while True:
        if len(title) >= 100:
            raise ValueError()

        line = f.readline().strip()

        if line[:5].upper() not in blocks:
            title.append(line)

        else:
            break

    if title:
        parameters["title"] = title[0] if len(title) == 1 else title

    f.seek(0)

    # Loop over blocks
    # Some blocks (INCON, INDOM, PARAM) need to rewind to previous line but tell and seek are disabled by next
    # See <https://stackoverflow.com/questions/22688505/is-there-a-way-to-go-back-when-reading-a-file-using-seek-and-calls-to-next>
    fiter = FileIterator(f)

    try:
        for line in fiter:
            if line.startswith("ROCKS"):
                parameters.update(_read_rocks(fiter))

            elif line.startswith("RPCAP"):
                rpcap = _read_rpcap(fiter)

                if "default" in parameters.keys():
                    parameters["default"].update(rpcap)

                else:
                    parameters["default"] = rpcap

            elif line.startswith("FLAC"):
                flac = _read_flac(fiter, parameters["rocks_order"])
                parameters["flac"] = flac["flac"]

                for k, v in flac["rocks"].items():
                    parameters["rocks"][k].update(v)

            elif line.startswith("CHEMP"):
                parameters.update(_read_chemp(fiter))

            elif line.startswith("NCGAS"):
                parameters.update(_read_ncgas(fiter))

            elif line.startswith("MULTI"):
                parameters.update(_read_multi(fiter))

            elif line.startswith("SOLVR"):
                parameters.update(_read_solvr(fiter))

            elif line.startswith("START"):
                parameters["start"] = True

            elif line.startswith("PARAM"):
                param = _read_param(fiter, eos)
                parameters["options"] = param["options"]
                parameters["extra_options"] = param["extra_options"]

                if "default" in parameters.keys():
                    parameters["default"].update(param["default"])

                else:
                    parameters["default"] = param["default"]

            elif line.startswith("SELEC"):
                parameters.update(_read_selec(fiter))

            elif line.startswith("INDOM"):
                indom = _read_indom(fiter, eos)

                for k, v in indom["rocks"].items():
                    parameters["rocks"][k].update(v)

            elif line.startswith("MOMOP"):
                parameters.update(_read_momop(fiter))

            elif line.startswith("TIMES"):
                parameters.update(_read_times(fiter))

            elif line.startswith("FOFT"):
                parameters.update(_read_oft(fiter, "FOFT", label_length))

            elif line.startswith("COFT"):
                parameters.update(_read_oft(fiter, "COFT", label_length))

            elif line.startswith("GOFT"):
                parameters.update(_read_oft(fiter, "GOFT", label_length))

            elif line.startswith("GENER"):
                parameters.update(_read_gener(fiter, label_length))

            elif line.startswith("DIFFU"):
                parameters.update(_read_diffu(fiter))

            elif line.startswith("OUTPU"):
                parameters.update(_read_outpu(fiter))

            elif line.startswith("ELEME"):
                parameters.update(_read_eleme(fiter, label_length))
                parameters["coordinates"] = False

            elif line.startswith("COORD"):
                coord = _read_coord(fiter)

                for k, v in zip(parameters["elements_order"], coord):
                    parameters["elements"][k]["center"] = v

                parameters["coordinates"] = True

            elif line.startswith("CONNE"):
                conne, flag = _read_conne(fiter, label_length)
                parameters.update(conne)

                if flag:
                    break

            elif line.startswith("INCON"):
                incon, flag = _read_incon(fiter, label_length, eos)
                parameters.update(incon)

                if flag:
                    break

            elif line.startswith("MESHM"):
                parameters.update(_read_meshm(fiter))

            elif line.startswith("NOVER"):
                parameters["nover"] = True

            elif line.startswith("ENDCY"):
                break

    except:
        raise ReadError("failed to parse line {}.".format(fiter.count))

    return parameters


def _read_rocks(f):
    """Read ROCKS block data."""
    fmt = block_to_format["ROCKS"]
    rocks = {"rocks": {}, "rocks_order": []}

    while True:
        line = f.next()

        if line.strip():
            # Record 1
            data = read_record(line, fmt[1])
            rock = data[0]
            rocks["rocks"][rock] = {
                "density": data[2],
                "porosity": data[3],
                "permeability": data[4] if len(set(data[4:7])) == 1 else data[4:7],
                "conductivity": data[7],
                "specific_heat": data[8],
            }

            nad = data[1]
            if nad is not None:
                # Record 2
                line = f.next()
                data = read_record(line, fmt[2])
                rocks["rocks"][rock].update(
                    {
                        "compressibility": data[0],
                        "expansivity": data[1],
                        "conductivity_dry": data[2],
                        "tortuosity": data[3],
                        "klinkenberg_parameter": data[4],
                        "distribution_coefficient_3": data[5],
                        "distribution_coefficient_4": data[6],
                    }
                )

            if nad and nad > 1:
                rocks["rocks"][rock].update(_read_rpcap(f))

            rocks["rocks_order"].append(rock)
        else:
            break

    rocks["rocks"] = {k: prune_nones_dict(v) for k, v in rocks["rocks"].items()}

    return rocks


def _read_rpcap(f):
    """Read RPCAP block data."""
    fmt = block_to_format["RPCAP"]
    rpcap = {}

    for key in ["relative_permeability", "capillarity"]:
        line = f.next()
        data = read_record(line, fmt)
        if data[0] is not None:
            rpcap[key] = {
                "id": data[0],
                "parameters": prune_nones_list(data[2:]),
            }

    return rpcap


def _read_flac(f, rocks_order):
    """Read FLAC block data."""
    fmt = block_to_format["FLAC"]
    flac = {"rocks": {}, "flac": {}}

    # Record 1
    line = f.next()
    data = read_record(line, fmt[1])
    flac["flac"]["creep"] = data[0]
    flac["flac"]["porosity_model"] = data[1]
    flac["flac"]["version"] = data[2]

    # Additional records
    for rock in rocks_order:
        flac["rocks"][rock] = {}

        line = f.next()
        data = read_record(line, fmt[2])
        flac["rocks"][rock]["permeability_model"] = {
            "id": data[0],
            "parameters": prune_nones_list(data[1:]),
        }

        line = f.next()
        data = read_record(line, fmt[3])
        flac["rocks"][rock]["equivalent_pore_pressure"] = {
            "id": data[0],
            "parameters": prune_nones_list(data[2:]),
        }

    flac["flac"] = prune_nones_dict(flac["flac"])

    return flac


def _read_chemp(f):
    """Read CHEMP block data."""
    fmt = block_to_format["CHEMP"]
    chemp = {"chemical_properties": {}}

    # Record 1
    line = f.next()
    n = read_record(line, fmt[1])[0]

    # Record 2
    for _ in range(n):
        tmp = {}

        line = f.next()
        data = read_record(line, fmt[2])
        chem = data[0]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["temperature_crit"] = data[0]
        tmp["pressure_crit"] = data[1]
        tmp["compressibility_crit"] = data[2]
        tmp["pitzer_factor"] = data[3]
        tmp["dipole_moment"] = data[4]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["boiling_point"] = data[0]
        tmp["vapor_pressure_a"] = data[1]
        tmp["vapor_pressure_b"] = data[2]
        tmp["vapor_pressure_c"] = data[3]
        tmp["vapor_pressure_d"] = data[4]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["molecular_weight"] = data[0]
        tmp["heat_capacity_a"] = data[1]
        tmp["heat_capacity_b"] = data[2]
        tmp["heat_capacity_c"] = data[3]
        tmp["heat_capacity_d"] = data[4]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["napl_density_ref"] = data[0]
        tmp["napl_temperature_ref"] = data[1]
        tmp["gas_diffusivity_ref"] = data[2]
        tmp["gas_temperature_ref"] = data[3]
        tmp["exponent"] = data[4]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["napl_viscosity_a"] = data[0]
        tmp["napl_viscosity_b"] = data[1]
        tmp["napl_viscosity_c"] = data[2]
        tmp["napl_viscosity_d"] = data[3]
        tmp["volume_crit"] = data[4]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["solubility_a"] = data[0]
        tmp["solubility_b"] = data[1]
        tmp["solubility_c"] = data[2]
        tmp["solubility_d"] = data[3]

        line = f.next()
        data = read_record(line, fmt[3])
        tmp["oc_coeff"] = data[0]
        tmp["oc_fraction"] = data[1]
        tmp["oc_decay"] = data[2]

        chemp["chemical_properties"][chem] = tmp

    return chemp


def _read_ncgas(f):
    """Read NCGAS block data."""
    fmt = block_to_format["NCGAS"]
    ncgas = {"non_condensible_gas": []}

    # Record 1
    line = f.next()
    n = read_record(line, fmt[1])[0]

    # Record 2
    for _ in range(n):
        line = f.next()
        data = read_record(line, fmt[2])
        ncgas["non_condensible_gas"].append(data[0])

    return ncgas


def _read_multi(f):
    """Read MULTI block data."""
    fmt = block_to_format["MULTI"]
    multi = {}

    line = f.next()
    data = read_record(line, fmt)
    multi["n_component"] = data[0]
    multi["isothermal"] = data[1] == data[0]
    multi["n_phase"] = data[2]
    multi["n_component_incon"] = data[4]

    return multi


def _read_solvr(f):
    """Read SOLVR block data."""
    fmt = block_to_format["SOLVR"]
    solvr = {}

    line = f.next()
    data = read_record(line, fmt)
    solvr["solver"] = {
        "method": data[0],
        "z_precond": data[2],
        "o_precond": data[4],
        "rel_iter_max": data[5],
        "eps": data[6],
    }

    return solvr


def _read_param(f, eos=None):
    """Read PARAM block data."""
    fmt = block_to_format["PARAM"]
    param = {}

    # Record 1
    line = f.next()
    data = read_record(line, fmt[1])
    param["options"] = {
        "n_iteration": data[0],
        "verbosity": data[1],
        "n_cycle": data[2],
        "n_second": data[3],
        "n_cycle_print": data[4],
        "temperature_dependence_gas": data[7],
        "effective_strength_vapor": data[8],
    }
    param["extra_options"] = {
        i + 1: int(x) for i, x in enumerate(data[5]) if x.isdigit()
    }

    # Record 2
    line = f.next()
    data = read_record(line, fmt[2])
    param["options"].update(
        {
            "t_ini": data[0],
            "t_max": data[1],
            "t_steps": data[2],
            "t_step_max": data[3],
            "gravity": data[5],
            "t_reduce_factor": data[6],
            "mesh_scale_factor": data[7],
        }
    )

    t_steps = int(data[2])
    if t_steps >= 0.0:
        param["options"]["t_steps"] = t_steps
    else:
        param["options"]["t_steps"] = []
        for _ in range(-t_steps):
            line = f.next()
            data = read_record(line, fmt[3])
            param["options"]["t_steps"] += prune_nones_list(data)
        if len(param["options"]["t_steps"]) == 1:
            param["options"]["t_steps"] = param["options"]["t_steps"][0]

    # Record 3
    line = f.next()
    data = read_record(line, fmt[4])
    param["options"].update(
        {
            "eps1": data[0],
            "eps2": data[1],
            "w_upstream": data[3],
            "w_newton": data[4],
            "derivative_factor": data[5],
        }
    )

    # Record 4 (TMVOC)
    if eos == "tmvoc":
        line = f.next()
        data = read_record(line, "5d")
        param["default"] = {"phase_composition": data[0]}

    # Record 4 and record 5 (EOS7R)
    line = f.next()
    data = read_record(line, fmt[5])

    i = f.tell()
    try:
        line = f.next()
        data += read_record(line, fmt[5])
    except ValueError:
        f.seek(i, increment=-1)

    if "default" not in param:
        param["default"] = {}

    if any(x is not None for x in data):
        data = prune_nones_list(data)
        param["default"]["initial_condition"] = data

    # Remove Nones
    param["options"] = prune_nones_dict(param["options"])
    param["extra_options"] = prune_nones_dict(param["extra_options"])

    return param


def _read_selec(f):
    """Read SELEC block data."""
    fmt = block_to_format["SELEC"]
    selec = {"selections": {}}

    line = f.next()
    data = read_record(line, fmt[1])
    selec["selections"]["integers"] = {k + 1: v for k, v in enumerate(data)}

    if selec["selections"]["integers"][1]:
        selec["selections"]["floats"] = []
        for _ in range(selec["selections"]["integers"][1]):
            line = f.next()
            data = read_record(line, fmt[2])
            selec["selections"]["floats"].append(prune_nones_list(data))

    selec["selections"]["integers"] = prune_nones_dict(selec["selections"]["integers"])
    if selec["selections"]["integers"][1] == 1:
        selec["selections"]["floats"] = selec["selections"]["floats"][0]

    return selec


def _read_indom(f, eos=None):
    """Read INDOM block data."""
    fmt = block_to_format["INDOM"]
    indom = {"rocks": {}}

    line = f.next()
    two_lines = True
    while True:
        if line.strip():
            # Record 1
            data = read_record(line, fmt[5])
            rock = data[0]
            phase_composition = data[1]  # TMVOC

            # Record 2
            line = f.next()
            data = read_record(line, fmt[0])

            # Record 3 (EOS7R)
            if two_lines:
                i = f.tell()
                line = f.next()

                if line.strip():
                    try:
                        data += read_record(line, fmt[0])
                    except ValueError:
                        two_lines = False
                        f.seek(i, increment=-1)
                else:
                    f.seek(i, increment=-1)

            data = prune_nones_list(data)
            indom["rocks"][rock] = {"initial_condition": data}

            if eos == "tmvoc":
                indom["rocks"][rock]["phase_composition"] = phase_composition

        else:
            break

        line = f.next()

    return indom


def _read_momop(f):
    """Read MOMOP block data."""
    fmt = block_to_format["MOMOP"]

    line = f.next()
    data = read_record(line, fmt)
    momop = {
        "more_options": {i + 1: int(x) for i, x in enumerate(data[0]) if x.isdigit()}
    }

    return momop


def _read_times(f):
    """Read TIMES block data."""
    fmt = block_to_format["TIMES"]
    times = {"times": []}

    # Record 1
    line = f.next()
    data = read_record(line, fmt[1])
    n_times = data[0]

    # Record 2
    while len(times["times"]) < n_times:
        line = f.next()
        data = read_record(line, fmt[2])
        times["times"] += prune_nones_list(data)

    return times


def _read_oft(f, oft, label_length):
    """Read FOFT, COFT and GOFT blocks data."""
    key = oft_to_key[oft]
    fmt = block_to_format[oft]
    history = {key: []}

    line = f.next()
    if not label_length:
        label_length = get_label_length(line[:9])

    while True:
        if line.strip():
            data = read_record(line, fmt[label_length])
            history[key].append(data[0])

        else:
            break

        line = f.next()

    return history


def _read_gener(f, label_length):
    """Read GENER block data."""
    fmt = block_to_format["GENER"]
    gener = {"generators": []}

    line = f.next()
    if not label_length:
        label_length = get_label_length(line[:9])

    while True:
        if line.strip():
            data = read_record(line, fmt[label_length])
            tmp = {
                "label": data[0],
                "name": data[1],
                "nseq": data[2],
                "nadd": data[3],
                "nads": data[4],
                "type": data[7],
                "layer_thickness": data[11],
            }

            ltab = data[5]
            if ltab and ltab > 1:
                itab = data[8]
                keys = ["times", "rates"]
                keys += ["specific_enthalpy"] if itab else []
                for key in keys:
                    table = []

                    while len(table) < ltab:
                        line = f.next()
                        data = read_record(line, fmt[0])
                        table += prune_nones_list(data)

                    tmp[key] = table

            else:
                tmp.update(
                    {"times": None, "rates": data[9], "specific_enthalpy": data[10],}
                )

            gener["generators"].append(tmp)

        else:
            break

        line = f.next()

    return {
        "generators": [prune_nones_dict(generator) for generator in gener["generators"]]
    }


def _read_diffu(f):
    """Read DIFFU block data."""
    fmt = block_to_format["DIFFU"]
    diffu = {"diffusion": []}

    while True:
        i = f.tell()
        line = f.next()

        if line.split():
            try:
                data = read_record(line, fmt)
                diffu["diffusion"].append(prune_nones_list(data))
            except ValueError:
                f.seek(i, increment=-1)
                break
        else:
            break

    return diffu


def _read_outpu(f):
    """Read OUTPU block data."""
    fmt = block_to_format["OUTPU"]
    outpu = {"output": {}}

    # Format
    line = f.next().strip()
    if line and not line.isdigit():
        outpu["output"]["format"] = line if line else None
        line = f.next().strip()

    # Variables
    if line.isdigit():
        num_vars = int(line)
        outpu["output"]["variables"] = []

        for _ in range(num_vars):
            line = f.next()
            data = read_record(line, fmt[3])
            name = data[0].lower()

            tmp = prune_nones_list(data[1:])
            options = None if len(tmp) == 0 else tmp[0] if len(tmp) == 1 else tmp

            outpu["output"]["variables"].append({"name": name})
            if options is not None:
                outpu["output"]["variables"][-1]["options"] = options

    return outpu


def _read_eleme(f, label_length):
    """Read ELEME block data."""
    fmt = block_to_format["ELEME"]
    eleme = {"elements": {}, "elements_order": []}

    line = f.next()
    if not label_length:
        label_length = get_label_length(line[:9])

    while True:
        if line.strip():
            data = read_record(line, fmt[label_length])
            label = data[0]
            rock = data[3].strip()
            eleme["elements"][label] = {
                "nseq": data[1],
                "nadd": data[2],
                "material": int(rock) if all(r.isdigit() for r in rock) else rock,
                "volume": data[4],
                "heat_exchange_area": data[5],
                "permeability_modifier": data[6],
                "center": data[7:10],
            }

            eleme["elements_order"].append(label)
        else:
            break

        line = f.next()

    eleme["elements"] = {k: prune_nones_dict(v) for k, v in eleme["elements"].items()}

    return eleme


def _read_coord(f):
    """Read COORD block data."""
    fmt = block_to_format["COORD"]
    coord = []

    line = f.next()
    while True:
        if line.strip():
            data = read_record(line, fmt)
            coord.append(data)
        else:
            break

        line = f.next()

    return coord


def _read_conne(f, label_length):
    """Read CONNE block data."""
    fmt = block_to_format["CONNE"]
    conne = {"connections": {}, "connections_order": []}

    line = f.next()
    if not label_length:
        label_length = get_label_length(line[:9])

    flag = False
    while True:
        if line.strip() and not line.startswith("+++"):
            data = read_record(line, fmt[label_length])
            label = data[0]
            conne["connections"][label] = {
                "nseq": data[1],
                "nadd": data[2:4],
                "permeability_direction": data[4],
                "nodal_distances": data[5:7],
                "interface_area": data[7],
                "gravity_cosine_angle": data[8],
                "radiant_emittance_factor": data[9],
            }

            conne["connections_order"].append(label)
        else:
            flag = line.startswith("+++")
            break

        line = f.next()

    conne["connections"] = {
        k: prune_nones_dict(v) for k, v in conne["connections"].items()
    }

    return conne, flag


def _read_incon(f, label_length, eos=None):
    """Read INCON block data."""
    fmt = block_to_format["INCON"]
    fmt2 = fmt[eos] if eos in fmt else fmt["default"]
    incon = {"initial_conditions": {}, "initial_conditions_order": []}

    line = f.next()
    if not label_length:
        label_length = get_label_length(line[:9])

    flag = False
    two_lines = True
    while True:
        if line.strip() and not line.startswith("+++"):
            # Record 1
            data = read_record(line, fmt2[label_length])
            label = data[0]
            incon["initial_conditions"][label] = {"porosity": data[3]}

            if eos == "tmvoc":
                incon["initial_conditions"][label]["phase_composition"] = data[4]

            else:
                userx = prune_nones_list(data[4:9])
                incon["initial_conditions"][label]["userx"] = userx if userx else None

            # Record 2
            line = f.next()
            data = read_record(line, fmt[0])

            # Record 3 (EOS7R)
            if two_lines:
                i = f.tell()
                line = f.next()

                if line.strip() and not line.startswith("+++"):
                    try:
                        data += read_record(line, fmt[0])
                    except ValueError:
                        two_lines = False
                        f.seek(i, increment=-1)
                else:
                    f.seek(i, increment=-1)

            incon["initial_conditions"][label]["values"] = prune_nones_list(data)
            incon["initial_conditions_order"].append(label)
        else:
            flag = line.startswith("+++")
            break

        line = f.next()

    incon["initial_conditions"] = {
        k: prune_nones_dict(v) for k, v in incon["initial_conditions"].items()
    }

    return incon, flag


def _read_meshm(f):
    """Read MESHM block data."""
    meshm = {"meshmaker": {}}
    fmt = block_to_format["MESHM"]

    # Mesh type
    line = f.next().strip()
    data = read_record(line, fmt[1])
    mesh_type = data[0].upper()

    # XYZ
    if mesh_type == "XYZ":
        meshm["meshmaker"]["type"] = mesh_type.lower()
        fmt = fmt["XYZ"]

        # Record 1
        line = f.next().strip()
        data = read_record(line, fmt[1])
        meshm["meshmaker"]["angle"] = data[0]

        # Record 2
        meshm["meshmaker"]["parameters"] = []

        while True:
            line = f.next()

            if line.strip():
                data = read_record(line, fmt[2])
                tmp = {
                    "type": data[0].lower(),
                    "n_increment": data[1],
                }

                if data[2]:
                    tmp["sizes"] = data[2]

                else:
                    sizes = []
                    while len(sizes) < tmp["n_increment"]:
                        line = f.next()
                        data = read_record(line, fmt[3])
                        sizes += prune_nones_list(data)

                    tmp["sizes"] = sizes[: tmp["n_increment"]]

                meshm["meshmaker"]["parameters"].append(tmp)

            else:
                break

    # RZ2D
    elif mesh_type in {"RZ2D", "RZ2DL"}:
        meshm["meshmaker"]["type"] = mesh_type.lower()
        fmt = fmt["RZ2D"]

        # Record 1
        meshm["meshmaker"]["parameters"] = []

        while True:
            line = f.next()

            if line.strip():
                data = read_record(line, fmt[1])
                data_type = data[0].upper()

                if data_type == "RADII":
                    line = f.next()
                    data = read_record(line, fmt["RADII"][1])
                    n = data[0]

                    radii = []
                    while len(radii) < n:
                        line = f.next()
                        data = read_record(line, fmt["RADII"][2])
                        radii += prune_nones_list(data)

                    tmp = {
                        "type": data_type.lower(),
                        "radii": radii[:n],
                    }
                    meshm["meshmaker"]["parameters"].append(tmp)

                elif data_type == "EQUID":
                    line = f.next()
                    data = read_record(line, fmt["EQUID"])

                    tmp = {
                        "type": data_type.lower(),
                        "n_increment": data[0],
                        "size": data[2],
                    }
                    meshm["meshmaker"]["parameters"].append(tmp)

                elif data_type == "LOGAR":
                    line = f.next()
                    data = read_record(line, fmt["LOGAR"])

                    tmp = {
                        "type": data_type.lower(),
                        "n_increment": data[0],
                        "radius": data[2],
                        "radius_ref": data[3],
                    }
                    meshm["meshmaker"]["parameters"].append(tmp)

                elif data_type == "LAYER":
                    # Record 1
                    line = f.next()
                    data = read_record(line, fmt["LAYER"][1])
                    n = data[0]

                    # Record 2
                    thicknesses = []
                    while len(thicknesses) < n:
                        line = f.next()
                        data = read_record(line, fmt["LAYER"][2])
                        thicknesses += prune_nones_list(data)

                    tmp = {"type": data_type.lower(), "thicknesses": thicknesses[:n]}
                    meshm["meshmaker"]["parameters"].append(tmp)

            else:
                break

    return meshm
