classdef Motor < Bay
    % Motor: Represents the motor configuration for a rocket.
    %
    %   Constructor:
    %       - Motor: Creates an instance of the Motor class.
    %           Loaded config: rocketConfig.m > motor
    %           Loaded data: motors.mat
    %           Arguments:
    %               - mission: Mission, mission object
    %               - varIn: (optional) config source. Alternative to config.m file

    properties
        name                {mustBeTextScalar} = '' % [-]  Motor name
        position                                    % [m] Absolute position, relative to nose base
        length                                      % [m]  Total length (motor + tank)
        inertia                                     % [kg*m^2] Total Motor inertia (Body reference)
        cutoffTime          double                  % [s]  Shutdown time
        tankLength          double                  % [m]  Tank length
        ignitionTransient   double                  % [s]  Ignition transient duration
        cutoffTransient     double                  % [s]  Cutoff transient duration
        time                double                  % [s]  Engine time vector
        thrust              double                  % [N]  Engine thrust vector
        fuelMass            double                  % [kg] Fuel (grain) initial mass
        oxidizerMass        double                  % [kg] Oxidizer initial mass
        propellantMass      double                  % [Kg] Propellant Mass (in time)
        structureMass       double                  % [kg] Engine Structural Mass
        fuselageMass        double                  % [kg] Fuselage of the engine only
        xCg                                         % [m]  Engine xcg from tank tip
        pe                  double                  % [Pa] Eflux pressure
        ae                  double                  % [Pa] Eflux Area
    end

    properties
        mass                                        % [kg] Total Motor mass
        fuselageXCg         double                  % [m]  xcg of the engine fuselage only from tank tip
    end

    properties(Access = protected)
        configName = 'rocketConfig.m'
        variableName = 'motor'
        mission Mission = Mission()
    end

    properties(SetAccess = protected)
        isHRE             logical                   % [-] Flag relateed to the type of motor: true if HRE
    end
    
    methods
        function obj = Motor(mission, varIn)
            arguments(Input)
                mission Mission = Mission()
                varIn = []
            end
            obj@Bay(mission, varIn);
            obj.loadData();
            obj.updateAll();
        end

        function set.name(obj, name)
            obj.name = name;
            obj.loadData();
            obj.updateAll();
        end

        function updateAll(obj)
            obj.updateMass();
        end

        function updateMass(obj)
            obj.fuselageXCg = (obj.length - ...
                obj.tankLength)/2 + obj.tankLength;
            obj.mass = obj.propellantMass + obj.structureMass;
        end
    end

    methods (Access = protected)
        function obj = loadData(obj)
            if isempty(obj.mission.name) || isempty(obj.name)
                return;
            end
            load(fullfile(obj.mission.dataPath, 'motors.mat'), 'motors');
            chosenMotor = motors(strcmp({motors.MotorName}, obj.name));
            
            if ~(isempty(obj.name) || isvarname(obj.name))
                error('Motor name is not a valid MATLAB variable name')
            end

            if isempty(chosenMotor)
                error(strcat('Unable to find engine: ', obj.name));
            end

            obj.length              = chosenMotor.L;
            [obj.time, iUniqueTime] = unique(chosenMotor.t); 
            obj.thrust              = chosenMotor.T(iUniqueTime); 
            obj.propellantMass      = chosenMotor.m(iUniqueTime);
            obj.structureMass       = chosenMotor.mc;

            obj.isHRE = contains(obj.name, 'HRE');

            if obj.isHRE
                obj.tankLength      = chosenMotor.Ltank;      
                obj.fuelMass        = chosenMotor.mFu;  
                obj.oxidizerMass    = chosenMotor.mOx;        
                inertiaRaw          = [chosenMotor.Ixx;chosenMotor.Iyy;chosenMotor.Izz];
                obj.inertia         = inertiaRaw(:, iUniqueTime);
                obj.xCg             = chosenMotor.xcg(iUniqueTime);  
                obj.pe              = chosenMotor.Pe(iUniqueTime);   
                obj.ae              = chosenMotor.Ae;   
                obj.fuselageMass    = chosenMotor.mFus;                  
            end


            if isempty(obj.cutoffTime) || obj.cutoffTime > obj.time(end)
                obj.cutoffTime = obj.time(end);
            end
        end
    end
end