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",
}

allArgs = pd.DataFrame(
    [
        # General
        [
            "windingOrMetal",
            "General",
            "",
            "winding",
            "",
            "Switch between winding mode or metal design [winding, metal]",
            "",
        ],
        ["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],
            list,
            "Weights to the target function constituents: maxPuck, maxCritPuck, sumPuck, layerMass, maxStrainDiff, maxCritStrainDiff",
            "",
        ],
        [
            "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.",
            "",
        ],
        [
            "angleStartOfShoulderZone",
            "Optimization",
            "",
            None,
            float,
            "Angle above which the shoulder zone starts. If the highest stress is on the outer surface of the shoulder zone, a layer is added inside this zone. If not defined, this functionality is disabled.",
            "",
        ],
        [
            "optimizeHoopShifts",
            "Optimization",
            "",
            False,
            "",
            "Optimize the linear hoop shift distributions of the hoop layer patterns (still experimental)",
            "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",
            "",
        ],
        # 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.",
            "",
        ],
        ["polarOpeningRadius", "Geometry", "r_po", 20, float, "Polar opening radius [mm]", ""],
        [
            "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
        ["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",
            "",
        ],
        ["h2Mass", "Geometry", "", None, float, "H2 Mass, defines volume if given & no volume given"],
        [
            "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",
            "wing_at_engine",
            "",
            "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 lifes (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]",
            "",
        ],
        [
            "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]",
            "",
        ],
        [
            "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 hoop layers can be removed (may be possible due to high angle helicals taking up stress)",
            "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",
        ],
        ["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",
            "",
        ],
    ],
    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"]
