import pandas as pd

resultKeyToUnitDict = {
    "shellMass": "kg",
    "linerMass": "kg",
    "insulationMass": "kg",
    "fairingMass": "kg",
    "fittingMass": "kg",
    "totalMass": "kg",
    "volume": "dm^3",
    "h2Mass": "kg",
    "area": "m^2",
    "lengthAxial": "mm",
    "numberOfLayers": "",
    "cylinderThickness": "mm",
    "maxThickness": "mm",
    "reserveFactor": "",
    "gravimetricIndex": "",
    "stressRatio": "",
    "hoopHelicalRatio": "",
    "iterations": "",
    "duration": "s",
    "frpMassStrengthOnly": "kg",
    "frpMassFatigueOnly": "kg",
    "puckMax": "",
    "fatigueFactor": "",
    "angles": "°",
    "hoopLayerShifts1": "mm",
    "hoopLayerShifts2": "mm",
    "metalMass": "kg",
    "wallThickness": "mm",
    "bucklingFactorMass": "",
    "bucklingFactorSkinThickness": "",
    "numberOfRings": "",
    "ringWebThickness": "mm",
    "ringMass": "kg",
    "outerRadius": "mm",
}
for innerOuter in ["innerVessel_", "outerVessel_"]:
    resultKeyToUnitDict.update({innerOuter + key: value for key, value in resultKeyToUnitDict.items()})

allArgs = pd.DataFrame(
    [
        # General
        [
            "windingOrMetal",
            "General",
            "",
            "winding",
            "",
            "Switch between winding mode or metal design [winding, metal]",
            "",
        ],
        [
            "singleOrDoubleVessels",
            "General",
            "",
            "single",
            "",
            "Switch if a tank with one vessel or 2 vessels with vacuum insulation in between should be calculcated [single, double]",
            "",
        ],
        ["tankname", "General", "name", "tank_name", "", "Name of the tank", ""],
        ["nodeNumber", "General", "number", 500, int, "number of nodes along the contour", ""],
        ["verbose", "General", "", False, "", "More console output", "store_true"],
        ["verbosePlot", "General", "", False, "", "Plot the optimization target function", "store_true"],
        [
            "configFile",
            "General",
            "",
            None,
            "",
            "Config file to be used, which can be modified by further parameters",
            "",
        ],
        [
            "CPACSConfigFile",
            "General",
            "name",
            None,
            "",
            "CPACSConfigFile, it's parameters are prioritized over this configFile",
            "",
        ],
        [
            "tankuID",
            "General",
            "name",
            None,
            "",
            "tankuID of the tank to be imported from CPACSConfigFile",
            "",
        ],
        ["help", "General", "", "", "", "show this help message and exit", "help"],
        ["runDir", "General", "", None, "", "directory to save run", ""],
        # Optimization
        ["maxLayers", "Optimization", "layers", 200, int, "Maximum number of layers to be added", ""],
        [
            "relRadiusHoopLayerEnd",
            "Optimization",
            "",
            0.95,
            float,
            "relative radius (to cyl radius) where hoop layers end [-]",
            "",
        ],
        [
            "targetFuncWeights",
            "Optimization",
            "tfWeights",
            [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
            list,
            "Weights to the target function constituents: maxPuck, maxCritPuck, sumPuck, layerMass, maxStrainDiff, maxCritStrainDiff, sumStrainDiff",
            "",
        ],
        [
            "enforceWindableContour",
            "Optimization",
            "",
            False,
            "",
            "Modify target function to prefer layers that fulfill contour windability criteria: limit buildup and discourage concave surfaces near fitting",
            "store_true",
        ],
        [
            "hoopShiftRange",
            "Optimization",
            "",
            0,
            int,
            "number of hoop layers which are linearly spaced between the maximum and minimum hoop Shift. After this number of layers, the pattern is repeated. If set to 0 (default), then all layers are evenly spread out.",
            "",
        ],
        [
            "hoopLayerCluster",
            "Optimization",
            "",
            1,
            int,
            "number of hoop layers which are created as one cluster during the optimization.",
            "",
        ],
        [
            "sortLayers",
            "Optimization",
            "",
            False,
            "",
            "Sort Helical Layers by rising winding angle after adding each layer",
            "store_true",
        ],
        [
            "sortLayersAboveAngle",
            "Optimization",
            "",
            0.0,
            float,
            "Angle above which layers should be sorted and moved to the outside, when sortLayers is set to True.",
            "",
        ],
        [
            "optimizeHoopShifts",
            "Optimization",
            "",
            False,
            "",
            "Optimize the linear hoop shift distributions of the hoop layer patterns inside the final optimization step, when trying to remove layers",
            "store_true",
        ],
        [
            "findValidWindingAngles",
            "Optimization",
            "",
            False,
            "",
            "After optimization of each layer, find closest winding angles that result in valid patterns",
            "store_true",
        ],
        # Geometry
        [
            "dcyl",
            "Geometry",
            "d_cyl",
            400,
            float,
            "Diameter of the cylindrical section [mm]. Can be automatically adapted if volume is given",
            "",
        ],
        [
            "lcyl",
            "Geometry",
            "l_cyl",
            500,
            float,
            "Length of the cylindrical section [mm]. Can be automatically adapted if volume is given",
            "",
        ],
        ["lcylByR", "Geometry", "", 2.5, float, "only if lcyl is not given [-]", ""],
        [
            "volume",
            "Geometry",
            "",
            None,
            float,
            "Volume requirement [m**3]. If it does not fit to other geometry parameters, "
            "l_cyl is adapted and if l_cly would be below 150mm d_cyl is adapted",
            "",
        ],
        [
            "innerOuterPitch",
            "Geometry",
            "",
            100,
            float,
            "Distance between the inner contours of the inner and outer vessel [mm]",
        ],
        ["polarOpeningRadius", "Geometry", "r_po", 20, float, "Polar opening radius [mm]", ""],
        ["h2Mass", "Geometry", "", None, float, "H2 Mass, defines volume if given & no volume given"],
        # Geometry_Dome
        [
            "domeType",
            "Geometry_Dome",
            "",
            "isotensoid",
            "",
            "Shape of dome geometry [isotensoid, isotensoid_MuWind, circle, ellipse, torispherical, conical***, custom]",
            "",
        ],
        [
            "domeContour",
            "Geometry_Dome",
            "(x,r)",
            [None, None],
            "",
            "Must be given if domeType==custom. X- and R-array should be given without whitespaces like "
            '"[x1,x2],[r1,r2]" in [mm]',
            "",
        ],
        [
            "domeContourFile",
            "Geometry_Dome",
            "",
            None,
            "",
            "Alternative to specify a custom dome contour. A text file in /data which contains two space seperated rows (x and r values). Overwritten by domeContour if defined.",
            "",
        ],
        [
            "domeLengthByR",
            "Geometry_Dome",
            "l/r_cyl",
            0.5,
            float,
            "Axial length of the dome. Only used for domeType==ellipse [mm]",
            "",
        ],
        [
            "alpha",
            "Geometry_Dome",
            "(dcyl - dsmall)/dcyl",
            0.5,
            float,
            "ratio of the difference of cylindrical and small diameter to the cylindrical diameter",
            "",
        ],
        [
            "beta",
            "Geometry_Dome",
            "(lrad + lcone)/dcyl",
            1.5,
            float,
            "ratio of sum of the radial and conical length to the cylindrical diameter",
            "",
        ],
        [
            "gamma",
            "Geometry_Dome",
            "lrad/(lrad + lcone)",
            0.5,
            float,
            "ratio of the radial length to the sum of radial and conical length",
            "",
        ],
        [
            "delta1",
            "Geometry_Dome",
            "ldome/rsmall",
            0.5,
            float,
            "ratio of the semi axes of the elliptical dome end",
            "",
        ],
        [
            "r1ToD0",
            "Geometry_Dome",
            "r1/(2*r_cyl)",
            0.8,
            float,
            "ratio of the radius of the dish to the diameter of the cylinder (for torispherical domes)",
            "",
        ],
        [
            "r2ToD0",
            "Geometry_Dome",
            "r2/(2*r_cyl)",
            0.154,
            float,
            "ratio of the radius of the knuckle to the diameter of the cylinder (for torispherical domes)",
            "",
        ],
        # Geometry_Dome2
        [
            "dome2Type",
            "Geometry_Dome2",
            "",
            None,
            "",
            "Shape of dome geometry [isotensoid, isotensoid_MuWind, circle, ellipse, torispherical, custom]",
            "",
        ],
        [
            "dome2Contour",
            "Geometry_Dome2",
            "(x,r)",
            [None, None],
            "",
            "Must be given if domeType==custom. X- and R-array should be given without whitespaces like "
            '"[x1,x2],[r1,r2]" in [mm]',
            "",
        ],
        [
            "dome2ContourFile",
            "Geometry_Dome2",
            "",
            None,
            "",
            "Alternative to specify a custom dome contour for dome 2. A text file in /data which contains two space seperated rows (x and r values). Overwritten by domeContour if defined.",
            "",
        ],
        [
            "dome2LengthByR",
            "Geometry_Dome2",
            "l/r_cyl",
            0.5,
            float,
            "Axial length of the dome. Only used for domeType==ellipse [mm]",
            "",
        ],
        # Fitting
        ["includeFitting", "Fitting", "", True, "", "flag if a fitting for COPVs should be included", ""],
        ["fittingType", "Fitting", "", "A", "", "fitting type (A, B, or custom)", ""],
        ["r0", "Fitting", "r0", None, float, "valve radius  [mm]", ""],
        ["r1", "Fitting", "r1", None, float, "smaller disc radius [mm]", ""],
        ["rD", "Fitting", "rD", None, float, "wider disc radius [mm]", ""],
        ["dXB", "Fitting", "dXB", None, float, "boss length [mm]", ""],
        ["dX1", "Fitting", "dX1", None, float, "disc length [mm]", ""],
        ["dX2", "Fitting", "dX2", None, float, "distance from disc to wider boss section (only type B)[mm]", ""],
        ["lV", "Fitting", "lV", None, float, "valve length [mm]", ""],
        ["r3", "Fitting", "r3", None, float, "wider boss section radius (only type B) [mm]", ""],
        [
            "alphaP",
            "Fitting",
            "alphaP",
            None,
            float,
            "angle of boss widening (only type B) - 0° is steepest, 90° flattest [°]",
            "",
        ],
        ["rP", "Fitting", "rP", None, float, "radius of curvature of rounded section (only type B) [mm]", ""],
        [
            "customBossName",
            "Fitting",
            "",
            None,
            float,
            "Name of data file specifying custom boss contour as  [x y] differences starting from the polar opening",
            "",
        ],
        [
            "fittingMaterial",
            "Fitting",
            "fittingMat",
            "alu2219",
            "",
            "Fitting Material Name (defined in tankoh2.design.metal.material.)",
        ],
        # Design
        ["safetyFactor", "Design", "S", 2, float, "Safety factor used in design [-]", ""],
        ["helicalDesignFactor", "Design", "S_h", 1.0, float, "Additional Design factor used on the dome [-]", ""],
        [
            "valveReleaseFactor",
            "Design",
            "f_pv",
            1.0,
            float,
            "Factor defining additional pressure to account for the valve pressure inaccuracies",
            "",
        ],
        [
            "temperature",
            "Design",
            "",
            None,
            float,
            "Temperature, for differentiating between cryogenic and compressed storage and finding density [K]",
            "",
        ],
        ["pressure", "Design", "p_op", 1.0, float, "Operational pressure [MPa]", ""],
        ["minPressure", "Design", "p_op_min", 0.1, float, "Minimal operational pressure [MPa]", ""],
        ["maxFill", "Design", "p_b", 0.9, float, "Max fill level for liquid storage", ""],
        [
            "useHydrostaticPressure",
            "Design",
            "",
            False,
            "",
            "Flag whether hydrostatic pressure according to CS 25.963 (d) should be applied",
            "store_true",
        ],
        [
            "tankLocation",
            "Design",
            "loc",
            "fuselage",
            "",
            "Location of the tank according to CS 25.963 (d). Only used if useHydrostaticPressure. "
            "Options: [wing_no_engine, wing_at_engine, fuselage]",
            "",
        ],
        [
            "initialAnglesAndShifts",
            "Design",
            "angles,shifts_left,shifts_right",
            None,
            "",
            "3 lists defining angles and (left and right) shifts used before optimization starts",
            "",
        ],
        # Material
        [
            "materialName",
            "Material",
            "name",
            "CFRP_HyMod",
            "",
            "For metal tanks: name of the material defined in tankoh2.design.metal.material. "
            "For wound tanks: name of the .json for a µWind material definiton "
            "(e.g. in tankoh2/data/CFRP_HyMod.json). "
            "If only a name is given, the file is assumed to be in tankoh2/data",
            "",
        ],
        [
            "failureMode",
            "Material",
            "mode",
            "fibreFailure",
            "",
            "Use pucks failure mode [fibreFailure, interFibreFailure]",
            "",
        ],
        # Fiber roving parameters
        ["layerThk", "Fiber roving parameters", "thk", 0.125, float, "Thickness of layers [mm]", ""],
        [
            "layerThkHoop",
            "Fiber roving parameters",
            "thk",
            None,
            float,
            "Thickness of hoop (circumferential) layers [mm]",
            "",
        ],
        [
            "layerThkHelical",
            "Fiber roving parameters",
            "thk",
            None,
            float,
            "Thickness of helical layers [mm]. If None, layerThkHoop is used",
            "",
        ],
        ["rovingWidth", "Fiber roving parameters", "witdh", 3.175, float, "Width of one roving [mm]", ""],
        [
            "rovingWidthHoop",
            "Fiber roving parameters",
            "witdhHoop",
            None,
            float,
            "Width of one roving in hoop layer [mm]. If None, rovingWidth is used",
            "",
        ],
        [
            "rovingWidthHelical",
            "Fiber roving parameters",
            "witdhHelical",
            None,
            float,
            "Width of one roving in helical layer [mm]. If None, rovingWidth is used",
            "",
        ],
        [
            "numberOfRovings",
            "Fiber roving parameters",
            "number",
            4,
            int,
            "Number of rovings (rovingWidthHoop*numberOfRovings=bandWidth)",
            "",
        ],
        ["tex", "Fiber roving parameters", "", 446, float, "tex number [g/km]", ""],
        ["fibreDensity", "Fiber roving parameters", "", 1.78, float, "Fibre density [g/cm^3]", ""],
        # fatigue parameters
        [
            "operationalCycles",
            "Fatigue parameters",
            "",
            0,
            int,
            "Number of operational cycles from minPressure to pressure (if left at 0, no fatigue analysis is performed) [-]",
            "",
        ],
        ["zeroPressureCycles", "Fatigue parameters", "", 0, int, "Number of cycles to ambient T and p [-]", ""],
        ["simulatedTankLives", "Fatigue parameters", "", 5, int, "Number of simulated lives (scatter) [-]", ""],
        ["Kt", "Fatigue parameters", "Kt", 5.0, float, "Stress concentration factor [-]", ""],
        [
            "fatigueCyclePressure",
            "Fatigue parameters",
            "p_r",
            None,
            float,
            "pressure to apply for the fatigue cycles [MPa]. If left empty, working pressure is applied.",
            "",
        ],
        [
            "testPressureAfterFatigue",
            "Fatigue parameters",
            "p_r",
            None,
            float,
            "Test Pressure to survive after the cycles have been reached [MPa]",
            "",
        ],
        # aux materials
        ["linerThickness", "Aux Materials", "linerThk", 0.0, float, "Thickness of the liner [mm]", ""],
        ["insulationThickness", "Aux Materials", "insThk", 0.0, float, "Thickness of the insluation [mm]", ""],
        ["fairingThickness", "Aux Materials", "fairingThk", 0.0, float, "Thickness of the fairing [mm]", ""],
        ["linerMaterial", "Aux Materials", "linerMat", "PVDF", "", "Liner Material Name (in massdata.py)"],
        [
            "insulationMaterial",
            "Aux Materials",
            "insMat",
            "Rohacell41S",
            "",
            "Insulation Material Name (in massdata.py)",
        ],
        ["fairingMaterial", "Aux Materials", "fairingMat", "Kevlar", "", "Fairing Material Name (in massdata.py)"],
        [
            "useRstOutput",
            "Advanced Settings",
            "",
            False,
            "",
            "Flag to use rst output instead of indented text for results",
            "store_true",
        ],
        [
            "minCylindricalLength",
            "Advanced Settings",
            "",
            150,
            float,
            "Minimum cylindrical length allowed, due to muwind limitations [mm]",
            "",
        ],
        ["epsilon", "Advanced Settings", "epsilon", 1e-8, float, "Epsilon for floating point comparisons [-]", ""],
        [
            "reduceCylinder",
            "Advanced Settings",
            "",
            True,
            "",
            "Flag to use a reduced cylinder length to speed up the angle optimization",
            "store_true",
        ],
        [
            "optimizerSeed",
            "Advanced Settings",
            "",
            None,
            int,
            "Seed for evolutionary optimization for repeatable runs. If -1, no seed is used",
            "",
        ],
        [
            "maxThicknessDerivative",
            "Advanced Settings",
            "",
            0.5,
            float,
            "max Thickness/l-Coordinate derivative (thickness buildup rate) [mm/mm]",
            "",
        ],
        [
            "minThicknessDerivativeSorted",
            "Advanced Settings",
            "",
            -0.5,
            float,
            "min Thickness/l-Coordinate derivative (thickness decrease rate) over sorted layers [mm/mm]",
            "",
        ],
        [
            "useSectionPhi",
            "Advanced Settings",
            "",
            True,
            "",
            "Flag to use local muwind calculated fiber volume content from the winding analysis",
            "store_true",
        ],
        [
            "useThickShellScaling",
            "Advanced Settings",
            "",
            True,
            "",
            "Scales the layer stresses to match the analytical thick shell results for the tube section",
            "store_true",
        ],
        [
            "pullLowHelicalsToFitting",
            "Advanced Settings",
            "",
            True,
            "",
            "Pull helical layers which have a low opening radius (less than one bandwidth distance) to the fitting",
            "store_true",
        ],
        [
            "maxHoopShiftMuWind",
            "Advanced Settings",
            "",
            800,
            int,
            "Maximum possible hoop shift due to muwind limitations [mm]",
            "",
        ],
        [
            "hoopShiftBalance",
            "Advanced Settings",
            "",
            0.7,
            float,
            "Balance between hoop shifts into the dome and hoop shifts into the cylinder. If set to 2, hoop ends are shifted into the cylinder twice as far as into the dome; at 0.5, half as much.",
            "",
        ],
        [
            "hoopShiftMaxStagger",
            "Advanced Settings",
            "",
            0.3,
            float,
            "The maximum relative value of the distance between min and max hoop shift that individual hoop shift patterns can be staggered backwards, after which the next pattern starts at the max hoop shift again.",
            "",
        ],
        [
            "putHoopLayersOnLiner",
            "Advanced Settings",
            "",
            True,
            "",
            "When clustering hoop layers, the first cluster should be inside, directly on the liner. Otherwise, put helical layers first.",
            "store_true",
        ],
        [
            "putHoopLayersOnTop",
            "Advanced Settings",
            "",
            True,
            "",
            "When clustering hoop layers, the last cluster should be on top of the helical layers, but beneath the sorted layers. Otherwise, helical layers will be put there.",
            "store_true",
        ],
        [
            "ignoreLastElements",
            "Advanced Settings",
            "",
            8,
            int,
            "Number of Elements in the fitting region to ignore for the optimization. Stress is generally overestimated without the influence of the fitting.",
            "",
        ],
        [
            "removeObsoleteLayers",
            "Advanced Settings",
            "",
            True,
            "",
            "At the end of optimization, check if layers can be removed. If optimizeHoopShifts is True, this is also used here.",
            "store_true",
        ],
        [
            "preventHelicalBumps",
            "Advanced Settings",
            "",
            True,
            "",
            "During Optimization, move a fitting layer above the newly added layers to prevent bumps that will cause high stresses on future layers",
            "store_true",
        ],
        [
            "enforceRisingContourThickness",
            "Advanced Settings",
            "",
            True,
            "",
            "Enforce constantly rising thickness from the start of unsorted layers to the fitting (if using enforceWindableContour)",
            "store_true",
        ],
        [
            "useMoreCycles",
            "Advanced Settings",
            "",
            2,
            int,
            "Allow searching for closest valid angles with this many more cycles (and higher overlap)",
            "",
        ],
        ["maxHelicalAngle", "Advanced Settings", "", 74, float, "Maximum helical angle [°]", ""],
        [
            "useClairaultAngle",
            "Advanced Settings",
            "",
            True,
            "",
            "True: Use ClairaultAngle to calculate minimum Angle. False: Use optimizeAngle",
            "store_true",
        ],
        [
            "nodesPerBand",
            "Advanced Settings",
            "",
            8,
            int,
            "Minimum nodes per Bandwidth that will be enforced. 5-8 Nodes should prevent incorrect Muwind polarOpening errors.",
            "",
        ],
        [
            "contourFileSampling",
            "Advanced Settings",
            "",
            4,
            int,
            "Reduction of dome countour file samples by this factor",
            "",
        ],
        [
            "useThermomechanicalStress",
            "Advanced Settings",
            "",
            False,
            bool,
            "Flag if thermomechanical stresses due to temperature differences in operation should be considered (The feautre is fairly slow)",
            "",
        ],
        [
            "optimizerPopsize",
            "Advanced Settings",
            "optimizerPopsize",
            15,
            int,
            "Population size for evolutionary optimization",
            "",
        ],
        [
            "optimizerAtol",
            "Advanced Settings",
            "optimizerAtol",
            0.001,
            float,
            "Absolute tolerance for evolutionary optimization",
            "",
        ],
        # buckling parameters
        [
            "useBucklingCriterion",
            "Buckling parameters",
            "flag",
            False,
            "",
            "Calculate the buckling pressure according to NASA SP-8007",
            "",
        ],
        [
            "useBucklingSafety",
            "Buckling parameters",
            "flag",
            False,
            "",
            "Use the default safety factor (0.75) from NASA SP8007",
            "",
        ],
        [
            "useBucklingHydrostatic",
            "Buckling parameters",
            "flag",
            True,
            "",
            "Consider the hydrostatic component from NASA SP8007. It results in a in-plane load due to the hydrostatic pressure acting on the domes",
            "",
        ],
        [
            "ringHeight",
            "Buckling parameters",
            "",
            50,
            float,
            "height of the ring [mm]",
            "",
        ],
        [
            "ringFootWidth",
            "Buckling parameters",
            "",
            50,
            float,
            "foot width of the ring [mm]",
            "",
        ],
        [
            "numberOfRings",
            "Buckling parameters",
            "",
            5,
            int,
            "number of rings. Must be at least 2",
            "",
        ],
        [
            "ringCrossSectionType",
            "Buckling parameters",
            "",
            "T",
            str,
            "type of the ring cross section [T, Rectangle]",
            "",
        ],
        [
            "ringInertiaTransform",
            "Buckling parameters",
            "",
            "top-surface",
            str,
            "transform or not the inertia terms; accepts: null, mid-surface, top-surface, percent",
            "",
        ],
        [
            "ringInertiaTransformRatio",
            "Buckling parameters",
            "",
            0.5,
            float,
            "ratio of the ring height to be taken into account in percent when ringInertiaTransform=='percent'",
            "",
        ],
        [
            "ringMaterialName",
            "Buckling parameters",
            "",
            None,
            None,
            "Name of the ring material. If None is given, the cylinder material is used",
            "",
        ],
    ],
    columns=["name", "group", "metavar", "default", "type", "help", "action"],
)

#  keywords only used for winding calculations
windingOnlyKeywords = (
    allArgs[allArgs["group"] == "Fiber roving parameters"]["name"].tolist()
    + allArgs[allArgs["group"] == "Optimization"]["name"].tolist()
    + allArgs[allArgs["group"] == "Fitting"]["name"].tolist()
)
windingOnlyKeywords += ["failureMode"]
windingOnlyKeywords += ["initialAnglesAndShifts"]
