function output = enigma (mode,input)
    global the_enigma;
    initialize_the_enigma;
    if strcmp(mode,'encrypt') 
        output = encrypt (input);
    else
        if strcmp(mode,'decrypt')
            output = decrypt (input);
        end
    end

    % Rotate the wheel
    function rotate_wheel (i)
        the_enigma.rotor(i).wheel(1:the_enigma.chars) = [the_enigma.rotor(i).wheel(2:the_enigma.chars) the_enigma.rotor(i).wheel(1)];
    end

    % Rotate the wheels to the start position
    function initialize_rotors
        for i=1:1:the_enigma.rotors
            i
            x = 0
            the_enigma.rotor(i)
            the_enigma.rotor(i).wheel
            the_enigma.rotor(i).wheel(1)
            while (the_enigma.rotor(i).wheel(1)) ~= (the_enigma.rotor(i).start)
                x=x+1;
                x
                rotate_wheel (i);
            end
        end
    end

    % Initialize the_enigma machine
    function initialize_the_enigma   
        % This are the WWII settings added with a space
        % Use double or real to convert chars to real values
        wheel(1,:)  = double('EKMFLG DQVZNTOWYHXUSPAIBRCJ');
        wheel(2,:)  = double('UWYGADFPVZBECKMTHXSLRI NQOJ');
        wheel(3,:)  = double('AJDKSIRUXBLHWTMC QGZNPYFVOE');
        wheel(4,:)  = double('AJPCZWRLFBDKOTYUQGE NHXMIVS');
        wheel(5,:)  = double('BDFH JLCPRTXVZNYEIWGAKMUSQO');
        wheel(6,:)  = double('TAGBPCSDQEUFVNZ HYIXJWLRKOM');
        wheel(7,:)  = double('ESOVPZJAYQUIRHXLNFTGKDCMW B');
        wheel(8,:)  = double('HZWVARTN LGUPXQCEJMBSKDYOIF');
        wheel(9,:)  = double('VZBRGITYUPSDN HLXAWMJQOFECK');
        wheel(10,:) = double('QCYLXWENFTZOSMVJUDKGI ARPHB');
        wheel(11,:) = double('YRUHQSLDP XNGOKMIEBFZCWVJAT');
        wheel(12,:) = double('F VPJIAOYEDRZXWGCTKUQSBNMHL');
        % This are the selected wheels for encryption and decryption
        % You can assign different step sizes for rotation
        % To use all chars on the wheels the stepsize must be one
        % or mod(the_enigma.chars,stepsize(n)) must be greater null
        % The first rotor
        rotor(1) = struct ('wheel',wheel(5,:),'stepsize',1,'start',double('T'));
        % The second rotor
        rotor(2) = struct ('wheel',wheel(7,:),'stepsize',1,'start',double('V'));
        % The third rotor
        rotor(2) = struct ('wheel',wheel(11,:),'stepsize',1,'start',double('K'));
        % This is the_enigma
        the_enigma = struct('chars',27,'rotors',3,'rotor',rotor);
        % Initialize the rotors
        initialize_rotors;  
    end

    % Rotate the chain of wheels
    function rotate
        % Rotate the first wheel
        the_enigma.rotor(1).wheel = [the_enigma.rotor(1).wheel(2:the_enigma.chars) the_enigma.rotor(1).wheel(1)];
        for i=1:1:the_enigma.rotors-1
            % At the start position ?
            if the_enigma.rotor(i).wheel == the_enigma.rotor(i).start
                % Rotate the next wheel
                the_enigma.rotor(i+1).wheel = [the_enigma.rotor(i+1).wheel(2:the_enigma.chars) the_enigma.rotor(i+1).wheel(1)];
            end
        end
    end

    function ch = encrypt_char (ch)
        rotate;
        for i=1:1:the_enigma.rotors-1
            index = find(the_enigma.rotor(i).wheel,ch);
            ch = the_enigma.rotor(i+1).wheel(index);
        end
    end

    function encrypted_string = encrypt (string)
        % Preallocate memory
        encrypted_string = zeros(length(string),1);
        for i=1:1:length(string)
            encrypted_string(i) = encrypt_char(string(i));
        end
        return;
    end

    function ch = decrypt_char (ch)
        rotate;
        for i=the_enigma.rotors:-1:2
            index = find(the_enigma.rotor(i).wheel,ch);
            ch = the_enigma.rotor(i-1).wheel(index);
        end
        return;
    end

    function decrypted_string = decrypt (string)
        % Preallocate memery
        decrypted_string = zeros(length(string),1);
        for i=1:1:length(string)
            decrypted_string(i) = decrypt_char(string(i));
        end
    end

end