'''
The Quantum Espresso card module.  This works as a python wrapper of
cards used within quantum espresso.

- :class:`QeControl`
- :class:`QeSystem`
- :class:`QeElectrons`
- :class:`QeIons`
- :class:`QeCell`
- :class:`QeAtomicCoords`

------------

'''


class QeControl:
    '''
    The control card.  This is where the simulation type and background
    details are contained.

    **Parameters**

        calculation: *str*
            What type of calculation is to be run.  Options are:

            - scf:
            - nscf:
            - bands:
            - relax:
            - md:
            - vc-relax:
            - vc-md:

        title: *str*
            Extra string to print in output.
        verbosity: *str*
            What level of output is desired (high or low).
        restart_mode: *str*
            Are you restarting off a previous simulation (restart) or running
            a new simulation (from_scratch).
        wf_collect: *bool*
            Whether to save wavefunctions in the output directory (True) or
            not (False).
        nstep: *int*
            How many optimization steps to run.
        iprint: *int*
            This will write the band energies every *iprint* iterations.
        tstress: *bool*
            Whether to calculate the stress tensor (True) or not (False).
        tprnfor: *bool*
            Whether to calculate the forces (True) or not (false).
        dt: *float*
            The timestep in Rydberg atomic units for molecular dynamics.
            This unit is 1 a.u. = 4.8378E-17 s.
        outdir: *str*
            The output directory.
        wfcdir: *str*
            Directory for files generated by each processor.  In ICSE, this
            can be set as the outdir.
        prefix: *str*
            String to prepend to input and output files.
        lkpoint_dir: *bool*
            If False, instead of generating a directory for each k point,
            a single file is instead used.
        max_seconds: *float*
            Max cpu time a job can run for.
        etot_conv_thr: *float*
            Energy convergence criteria in a.u for ionic minimization.
        forc_conv_thr: *float*
            Force convergence criteria in a.u for ionic minimization.
        disk_io: *str*
            How much data to save to the disk.  Choices are high, medium,
            low, and none.
        pseudo_dir: *str*
            The folder where pseudopotential files are contained. Note, if
            nothing is passed then it is assumed to be the ESPRESSO_PSEUDO
            environment variable.
        tefield: *bool*
            If True, a saw-like potential simulating an electric field is
            added to the bare ionic potential.
        dipfield: *bool*
            If True, a dipole correction is added to the bare ionic potential.
            NOTE! Stipulations apply.  See quantum espresso documentation.
        lelfield: *bool*
            If True, a homogenous finite electric field from polarization is
            applied.
        nberrycyc: *int*
            If lelfield is used, this is the number of iterations for
            converging the wavefunctions in the electric field Hamiltonian.
        lorbm: *bool*
            If True, quantum espresso will run an orbital magnetization
            calculation.  Note, this only works with norm-conserving
            pseudopotentials.
        lberry: *bool*
            If True, perform a Berry phase calculation.  See Quantum Espresso
            for more information.
        gdir: *int*
            This is the direction of the k point strings in reciprocal space.
            Used for Berry phase calculation.
        nppstr: *int*
            The number of k-points to be calculated along each
            symmetry-reduced string.  Only used for Berry phase calculation.
        lfcpopt: *bool*
            If True, a constant bias potential calculation, for a static
            system, is run using the ESM method.  See Quantum Espresso for
            more information.
        monopole: *bool*
            In the instance of having a counter charge, setting monopole to
            True allows the user to define a charged plate instead of the
            default homogenous background charge.
    '''

    def __init__(self, calculation="scf", title="", verbosity="low",
                 restart_mode="from_scratch", wf_collect=False, nstep=None,
                 iprint=None, tstress=None):
        raise Exception("THIS HAS NOT BEEN WRITTEN YET!")


class QeAtomicCoords:
    '''
    This card combines the ATOMIC_SPECIES, ATOMIC_POSITIONS, and K_POINTS
    cards.
    '''

    def __init__(self):
        raise Exception("THIS HAS NOT BEEN WRITTEN YET!")
