text:
package ex03.pyrmont.connector.http;//package ex03.pyrmont.connector.http;
//
//import org.apache.catalina.util.StringManager;
//
//import java.io.EOFException;
//import java.io.IOException;
//import java.io.InputStream;
//
///**
// * Extends InputStream to be more efficient reading lines during HTTP
// * header processing.
// *
// * @author Remy Maucherat
// * @deprecated
// */
//public class SocketInputStream extends InputStream {
//
//
//    // -------------------------------------------------------------- Constants
//
//
//    /**
//     * CR.
//     */
//    private static final byte CR = (byte) '\r';
//
//
//    /**
//     * LF.
//     */
//    private static final byte LF = (byte) '\n';
//
//
//    /**
//     * SP.
//     */
//    private static final byte SP = (byte) ' ';
//
//
//    /**
//     * HT.
//     */
//    private static final byte HT = (byte) '\t';
//
//
//    /**
//     * COLON.
//     */
//    private static final byte COLON = (byte) ':';
//
//
//    /**
//     * Lower case offset.
//     */
//    private static final int LC_OFFSET = 'A' - 'a';
//
//
//    /**
//     * Internal buffer.
//     */
//    protected byte buf[];
//
//
//    /**
//     * Last valid byte.
//     */
//    protected int count;
//
//
//    /**
//     * Position in the buffer.
//     */
//    protected int pos;
//
//
//    /**
//     * Underlying input stream.
//     */
//    protected InputStream is;
//
//
//    // ----------------------------------------------------------- Constructors
//
//
//    /**
//     * Construct a servlet input stream associated with the specified socket
//     * input.
//     *
//     * @param is socket input stream
//     * @param bufferSize size of the internal buffer
//     */
//    public SocketInputStream (InputStream is, int bufferSize) {
//
//        this.is = is;
//        buf = new byte[bufferSize];
//
//    }
//
//
//    // -------------------------------------------------------------- Variables
//
//
//    /**
//     * The string manager for this package.
//     */
//    protected static StringManager sm =
//        StringManager.getManager(Constants.Package);
//
//
//    // ----------------------------------------------------- Instance Variables
//
//
//    // --------------------------------------------------------- Public Methods
//
//
//    /**
//     * Read the request line, and copies it to the given buffer. This
//     * function is meant to be used during the HTTP request header parsing.
//     * Do NOT attempt to read the request body using it.
//     *
//     * @param requestLine Request line object
//     * @throws IOException If an exception occurs during the underlying socket
//     * read operations, or if the given buffer is not big enough to accomodate
//     * the whole line.
//     */
//    public void readRequestLine(HttpRequestLine requestLine)
//        throws IOException {
//
//        // Recycling check
//        if (requestLine.methodEnd != 0)
//            requestLine.recycle();
//
//        // Checking for a blank line
//        int chr = 0;
//        do { // Skipping CR or LF
//            try {
//                chr = read();
//            } catch (IOException e) {
//                chr = -1;
//            }
//        } while ((chr == CR) || (chr == LF));
//        if (chr == -1)
//            throw new EOFException
//                (sm.getString("requestStream.readline.error"));
//        pos--;
//
//        // Reading the method name
//
//        int maxRead = requestLine.method.length;
//        int readStart = pos;
//        int readCount = 0;
//
//        boolean space = false;
//
//        while (!space) {
//            // if the buffer is full, extend it
//            if (readCount >= maxRead) {
//                if ((2 * maxRead) <= HttpRequestLine.MAX_METHOD_SIZE) {
//                    char[] newBuffer = new char[2 * maxRead];
//                    System.arraycopy(requestLine.method, 0, newBuffer, 0,
//                                     maxRead);
//                    requestLine.method = newBuffer;
//                    maxRead = requestLine.method.length;
//                } else {
//                    throw new IOException
//                        (sm.getString("requestStream.readline.toolong"));
//                }
//            }
//            // We're at the end of the internal buffer
//            if (pos >= count) {
//                int val = read();
//                if (val == -1) {
//                    throw new IOException
//                        (sm.getString("requestStream.readline.error"));
//                }
//                pos = 0;
//                readStart = 0;
//            }
//            if (buf[pos] == SP) {
//                space = true;
//            }
//            requestLine.method[readCount] = (char) buf[pos];
//            readCount++;
//            pos++;
//        }
//
//        requestLine.methodEnd = readCount - 1;
//
//        // Reading URI
//
//        maxRead = requestLine.uri.length;
//        readStart = pos;
//        readCount = 0;
//
//        space = false;
//
//        boolean eol = false;
//
//        while (!space) {
//            // if the buffer is full, extend it
//            if (readCount >= maxRead) {
//                if ((2 * maxRead) <= HttpRequestLine.MAX_URI_SIZE) {
//                    char[] newBuffer = new char[2 * maxRead];
//                    System.arraycopy(requestLine.uri, 0, newBuffer, 0,
//                                     maxRead);
//                    requestLine.uri = newBuffer;
//                    maxRead = requestLine.uri.length;
//                } else {
//                    throw new IOException
//                        (sm.getString("requestStream.readline.toolong"));
//                }
//            }
//            // We're at the end of the internal buffer
//            if (pos >= count) {
//                int val = read();
//                if (val == -1)
//                    throw new IOException
//                        (sm.getString("requestStream.readline.error"));
//                pos = 0;
//                readStart = 0;
//            }
//            if (buf[pos] == SP) {
//                space = true;
//            } else if ((buf[pos] == CR) || (buf[pos] == LF)) {
//                // HTTP/0.9 style request
//                eol = true;
//                space = true;
//            }
//            requestLine.uri[readCount] = (char) buf[pos];
//            readCount++;
//            pos++;
//        }
//
//        requestLine.uriEnd = readCount - 1;
//
//        // Reading protocol
//
//        maxRead = requestLine.protocol.length;
//        readStart = pos;
//        readCount = 0;
//
//        while (!eol) {
//            // if the buffer is full, extend it
//            if (readCount >= maxRead) {
//                if ((2 * maxRead) <= HttpRequestLine.MAX_PROTOCOL_SIZE) {
//                    char[] newBuffer = new char[2 * maxRead];
//                    System.arraycopy(requestLine.protocol, 0, newBuffer, 0,
//                                     maxRead);
//                    requestLine.protocol = newBuffer;
//                    maxRead = requestLine.protocol.length;
//                } else {
//                    throw new IOException
//                        (sm.getString("requestStream.readline.toolong"));
//                }
//            }
//            // We're at the end of the internal buffer
//            if (pos >= count) {
//                // Copying part (or all) of the internal buffer to the line
//                // buffer
//                int val = read();
//                if (val == -1)
//                    throw new IOException
//                        (sm.getString("requestStream.readline.error"));
//                pos = 0;
//                readStart = 0;
//            }
//            if (buf[pos] == CR) {
//                // Skip CR.
//            } else if (buf[pos] == LF) {
//                eol = true;
//            } else {
//                requestLine.protocol[readCount] = (char) buf[pos];
//                readCount++;
//            }
//            pos++;
//        }
//
//        requestLine.protocolEnd = readCount;
//
//    }
//
//
//    /**
//     * Read a header, and copies it to the given buffer. This
//     * function is meant to be used during the HTTP request header parsing.
//     * Do NOT attempt to read the request body using it.
//     *
//     * @param requestLine Request line object
//     * @throws IOException If an exception occurs during the underlying socket
//     * read operations, or if the given buffer is not big enough to accomodate
//     * the whole line.
//     */
//    public void readHeader(HttpHeader header)
//        throws IOException {
//
//        // Recycling check
//        if (header.nameEnd != 0)
//            header.recycle();
//
//        // Checking for a blank line
//        int chr = read();
//        if ((chr == CR) || (chr == LF)) { // Skipping CR
//            if (chr == CR)
//                read(); // Skipping LF
//            header.nameEnd = 0;
//            header.valueEnd = 0;
//            return;
//        } else {
//            pos--;
//        }
//
//        // Reading the header name
//
//        int maxRead = header.name.length;
//        int readStart = pos;
//        int readCount = 0;
//
//        boolean colon = false;
//
//        while (!colon) {
//            // if the buffer is full, extend it
//            if (readCount >= maxRead) {
//                if ((2 * maxRead) <= HttpHeader.MAX_NAME_SIZE) {
//                    char[] newBuffer = new char[2 * maxRead];
//                    System.arraycopy(header.name, 0, newBuffer, 0, maxRead);
//                    header.name = newBuffer;
//                    maxRead = header.name.length;
//                } else {
//                    throw new IOException
//                        (sm.getString("requestStream.readline.toolong"));
//                }
//            }
//            // We're at the end of the internal buffer
//            if (pos >= count) {
//                int val = read();
//                if (val == -1) {
//                    throw new IOException
//                        (sm.getString("requestStream.readline.error"));
//                }
//                pos = 0;
//                readStart = 0;
//            }
//            if (buf[pos] == COLON) {
//                colon = true;
//            }
//            char val = (char) buf[pos];
//            if ((val >= 'A') && (val <= 'Z')) {
//                val = (char) (val - LC_OFFSET);
//            }
//            header.name[readCount] = val;
//            readCount++;
//            pos++;
//        }
//
//        header.nameEnd = readCount - 1;
//
//        // Reading the header value (which can be spanned over multiple lines)
//
//        maxRead = header.value.length;
//        readStart = pos;
//        readCount = 0;
//
//        int crPos = -2;
//
//        boolean eol = false;
//        boolean validLine = true;
//
//        while (validLine) {
//
//            boolean space = true;
//
//            // Skipping spaces
//            // Note : Only leading white spaces are removed. Trailing white
//            // spaces are not.
//            while (space) {
//                // We're at the end of the internal buffer
//                if (pos >= count) {
//                    // Copying part (or all) of the internal buffer to the line
//                    // buffer
//                    int val = read();
//                    if (val == -1)
//                        throw new IOException
//                            (sm.getString("requestStream.readline.error"));
//                    pos = 0;
//                    readStart = 0;
//                }
//                if ((buf[pos] == SP) || (buf[pos] == HT)) {
//                    pos++;
//                } else {
//                    space = false;
//                }
//            }
//
//            while (!eol) {
//                // if the buffer is full, extend it
//                if (readCount >= maxRead) {
//                    if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
//                        char[] newBuffer = new char[2 * maxRead];
//                        System.arraycopy(header.value, 0, newBuffer, 0,
//                                         maxRead);
//                        header.value = newBuffer;
//                        maxRead = header.value.length;
//                    } else {
//                        throw new IOException
//                            (sm.getString("requestStream.readline.toolong"));
//                    }
//                }
//                // We're at the end of the internal buffer
//                if (pos >= count) {
//                    // Copying part (or all) of the internal buffer to the line
//                    // buffer
//                    int val = read();
//                    if (val == -1)
//                        throw new IOException
//                            (sm.getString("requestStream.readline.error"));
//                    pos = 0;
//                    readStart = 0;
//                }
//                if (buf[pos] == CR) {
//                } else if (buf[pos] == LF) {
//                    eol = true;
//                } else {
//                    // FIXME : Check if binary conversion is working fine
//                    int ch = buf[pos] & 0xff;
//                    header.value[readCount] = (char) ch;
//                    readCount++;
//                }
//                pos++;
//            }
//
//            int nextChr = read();
//
//            if ((nextChr != SP) && (nextChr != HT)) {
//                pos--;
//                validLine = false;
//            } else {
//                eol = false;
//                // if the buffer is full, extend it
//                if (readCount >= maxRead) {
//                    if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
//                        char[] newBuffer = new char[2 * maxRead];
//                        System.arraycopy(header.value, 0, newBuffer, 0,
//                                         maxRead);
//                        header.value = newBuffer;
//                        maxRead = header.value.length;
//                    } else {
//                        throw new IOException
//                            (sm.getString("requestStream.readline.toolong"));
//                    }
//                }
//                header.value[readCount] = ' ';
//                readCount++;
//            }
//
//        }
//
//        header.valueEnd = readCount;
//
//    }
//
//
//    /**
//     * Read byte.
//     */
//    public int read()
//        throws IOException {
//        if (pos >= count) {
//            fill();
//            if (pos >= count)
//                return -1;
//        }
//        return buf[pos++] & 0xff;
//    }
//
//
//    /**
//     *
//     */
//    /*
//    public int read(byte b[], int off, int len)
//        throws IOException {
//
//    }
//    */
//
//
//    /**
//     *
//     */
//    /*
//    public long skip(long n)
//        throws IOException {
//
//    }
//    */
//
//
//    /**
//     * Returns the number of bytes that can be read from this input
//     * stream without blocking.
//     */
//    public int available()
//        throws IOException {
//        return (count - pos) + is.available();
//    }
//
//
//    /**
//     * Close the input stream.
//     */
//    public void close()
//        throws IOException {
//        if (is == null)
//            return;
//        is.close();
//        is = null;
//        buf = null;
//    }
//
//
//    // ------------------------------------------------------ Protected Methods
//
//
//    /**
//     * Fill the internal buffer using data from the undelying input stream.
//     */
//    protected void fill()
//        throws IOException {
//        pos = 0;
//        count = 0;
//        int nRead = is.read(buf, 0, buf.length);
//        if (nRead > 0) {
//            count = nRead;
//        }
//    }
//
//
//}


text:
require 'rbeapi/api'

##
# Eos is the toplevel namespace for working with Arista EOS nodes.
module Rbeapi
  ##
  # Api is module namespace for working with the EOS command API.
  module Api
    ##
    # The Bgp class implements global BGP router configuration.
    class Bgp < Entity
      attr_reader :neighbors

      def initialize(node)
        super(node)
        @neighbors = BgpNeighbors.new(node)
      end

      ##
      # get returns the BGP routing configuration from the nodes current
      # configuration.
      #
      # @example
      #   {
      #     bgp_as: <string>,
      #     router_id: <string>,
      #     shutdown: <string>,
      #     maximum_paths: <integer>,
      #     maximum_ecmp_paths: <integer>
      #     networks: [
      #       {
      #         prefix: <string>,
      #         masklen: <integer>,
      #         route_map: <string>
      #       },
      #       {
      #         prefix: <string>,
      #         masklen: <integer>,
      #         route_map: <string>
      #       }
      #     ],
      #     neighbors: {
      #       name: {
      #         peer_group: <string>,
      #         remote_as: <string>,
      #         send_community: <boolean>,
      #         shutdown: <boolean>,
      #         description: <string>,
      #         next_hop_selp: <boolean>,
      #         route_map_in: <string>,
      #         route_map_out: <string>
      #       },
      #       name: {
      #         peer_group: <string>,
      #         remote_as: <string>,
      #         send_community: <boolean>,
      #         shutdown: <boolean>,
      #         description: <string>,
      #         next_hop_selp: <boolean>,
      #         route_map_in: <string>,
      #         route_map_out: <string>
      #       },
      #       ...
      #     }
      #   }
      #
      # @return [nil, Hash<Symbol, Object>] Returns the BGP resource as a
      #   Hash.
      def get
        config = get_block('^router bgp .*')
        return nil unless config

        response = Bgp.parse_bgp_as(config)
        response.merge!(parse_router_id(config))
        response.merge!(parse_shutdown(config))
        response.merge!(parse_maximum_paths(config))
        response.merge!(parse_networks(config))
        response[:neighbors] = @neighbors.getall
        response
      end

      ##
      # parse_bgp_as scans the BGP routing configuration for the
      # AS number. Defined as a class method. Used by the BgpNeighbors
      # class below.
      #
      # @param config [String] The switch config.
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash attribute.
      def self.parse_bgp_as(config)
        value = config.scan(/^router bgp (\d+)/).first
        { bgp_as: value[0] }
      end

      ##
      # parse_router_id scans the BGP routing configuration for the
      # router ID.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash attribute.
      def parse_router_id(config)
        value = config.scan(/router-id ([^\s]+)/).first
        value = value ? value[0] : nil
        { router_id: value }
      end
      private :parse_router_id

      ##
      # parse_shutdown scans the BGP routing configuration for the
      # shutdown status.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @return [Hash<Symbol, Object>] resource hash attribute. Returns
      # true if shutdown, false otherwise.
      def parse_shutdown(config)
        value = config.include?('no shutdown')
        { shutdown: !value }
      end
      private :parse_shutdown

      ##
      # parse_maximum_paths scans the BGP routing configuration for the
      # maximum paths and maximum ecmp paths.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash attribute.
      def parse_maximum_paths(config)
        values = config.scan(/maximum-paths\s+(\d+)\s+ecmp\s+(\d+)/).first
        { maximum_paths: values[0].to_i, maximum_ecmp_paths: values[1].to_i }
      end
      private :parse_maximum_paths

      ##
      # parse_networks scans the BGP routing configuration for all
      # the network entries.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @return [Array<Hash>] Single element hash with Array of network hashes.
      def parse_networks(config)
        networks = []
        lines = config.scan(%r{network (.+)/(\d+)(?: route-map (\w+))*})
        lines.each do |prefix, mask, rmap|
          rmap = rmap == '' ? nil : rmap
          networks << { prefix: prefix, masklen: mask.to_i, route_map: rmap }
        end
        { networks: networks }
      end
      private :parse_networks

      ##
      # create will create a new instance of BGP routing on the node.
      # Optional parameters can be passed in to initialize BGP specific
      # settings.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #
      # @param bgp_as [String] The BGP autonomous system number to be
      #   configured for the local BGP routing instance.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts router_id [String] The BGP routing process router-id
      #   value.  When no ID has been specified (i.e. value not set), the
      #   local router ID is set to the following:
      #   * The loopback IP address when a single loopback interface is
      #     configured.
      #   * The loopback with the highest IP address when multiple loopback
      #     interfaces are configured.
      #   * The highest IP address on a physical interface when no loopback
      #     interfaces are configure
      #
      # @option opts maximum_paths [Integer] Maximum number of equal cost
      # paths.
      #
      # @option opts maximum_ecmp_paths [Integer] Maximum number of installed
      #   ECMP routes. The maximum_paths option must be set if
      #   maximum_ecmp_paths is set.
      #
      # @option opts enable [Boolean] If true then the BGP router is enabled.
      #   If false then the BGP router is disabled.
      #
      # @return [Boolean] returns true if the command completed successfully.
      def create(bgp_as, opts = {})
        if opts[:maximum_ecmp_paths] && !opts[:maximum_paths]
          message = 'maximum_paths must be set if maximum_ecmp_paths is set'
          raise ArgumentError, message
        end
        cmds = ["router bgp #{bgp_as}"]
        if opts.key?(:enable)
          cmds << (opts[:enable] == true ? 'no shutdown' : 'shutdown')
        end
        cmds << "router-id #{opts[:router_id]}" if opts.key?(:router_id)
        if opts.key?(:maximum_paths)
          cmd = "maximum-paths #{opts[:maximum_paths]}"
          if opts.key?(:maximum_ecmp_paths)
            cmd << " ecmp #{opts[:maximum_ecmp_paths]}"
          end
          cmds << cmd
        end
        configure(cmds)
      end

      ##
      # delete will delete the BGP routing instance from the node.
      #
      # ===Commands
      #   no router bgp <bgp_as>
      #
      # @return [Boolean] Returns true if the command completed successfully.
      def delete
        config = get
        return true unless config
        configure("no router bgp #{config[:bgp_as]}")
      end

      ##
      # default will configure the BGP routing  using the default
      # keyword.  This command has the same effect as deleting the BGP
      # routine instance from the nodes running configuration.
      #
      # ===Commands
      #   default router bgp <bgp_as>
      #
      # @return [Boolean] returns true if the command complete successfully
      def default
        config = get
        return true unless config
        configure("default router bgp #{config[:bgp_as]}")
      end

      ##
      # configure_bgp adds the command to go to BGP config mode.
      # Then it adds the passed in command. The commands are then
      # passed on to configure.
      #
      # @api private
      #
      # @param cmd [String] Command to run under BGP mode.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def configure_bgp(cmd)
        config = get_block('^router bgp .*')
        raise 'BGP router is not configured' unless config
        bgp_as = Bgp.parse_bgp_as(config)
        cmds = ["router bgp #{bgp_as[:bgp_as]}", cmd]
        configure(cmds)
      end
      private :configure_bgp

      ##
      # set_router_id sets the router_id for the BGP routing instance.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} router-id <router_id>
      #
      # @param opts [hash] Optional keyword arguments
      #
      # @option opts value [String] The BGP routing process router-id
      #   value. When no ID has been specified (i.e. value not set), the
      #   local router ID is set to the following:
      #   * The loopback IP address when a single loopback interface is
      #     configured.
      #   * The loopback with the highest IP address when multiple loopback
      #     interfaces are configured.
      #   * The highest IP address on a physical interface when no loopback
      #     interfaces are configure
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the router-id using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_router_id(opts = {})
        configure_bgp(command_builder('router-id', opts))
      end

      ##
      # set_shutdown configures the administrative state for the global
      # BGP routing process. The value option is not used by this method.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} shutdown
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts enable [Boolean] If enable is true then the BGP
      #   routing process is administratively enabled and if enable is
      #   False then the BGP routing process is administratively
      #   disabled.
      #
      # @option opts default [Boolean] Configure the router-id using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_shutdown(opts = {})
        raise 'set_shutdown has the value option set' if opts[:value]
        # Shutdown semantics are opposite of enable semantics so invert enable
        value = !opts[:enable]
        opts[:enable] = value
        configure_bgp(command_builder('shutdown', opts))
      end

      ##
      # set_maximum_paths sets the maximum number of equal cost paths and
      # the maximum number of installed ECMP routes.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default}
      #       maximum-paths <maximum_paths> [ecmp <maximum_ecmp_paths>]
      #
      # @param maximum_paths [Integer] Maximum number of equal cost paths.
      #
      # @param maximum_ecmp_paths [Integer] Maximum number of installed ECMP
      #   routes.
      #
      # @param opts [hash] Optional keyword arguments
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the maximum paths using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {})
        enable = opts.fetch(:enable, true)
        default = opts[:default] || false

        case default
        when true
          cmd = 'default maximum-paths'
        when false
          if enable
            cmd = "maximum-paths #{maximum_paths} ecmp #{maximum_ecmp_paths}"
          else
            cmd = 'no maximum-paths'
          end
        end
        configure_bgp(cmd)
      end

      ##
      # add_network creates a new instance of a BGP network on the node.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     network <prefix>/<masklen>
      #     route-map <route_map>
      #
      # @param prefix [String] The IPv4 prefix to configure as part of
      #   the network statement. The value must be a valid IPv4 prefix.
      #
      # @param masklen [String] The IPv4 subnet mask length in bits.
      #   The masklen must be in the valid range of 1 to 32.
      #
      # @param route_map [String] The route-map name to apply to the
      #   network statement when configured.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def add_network(prefix, masklen, route_map = nil)
        cmd = "network #{prefix}/#{masklen}"
        cmd << " route-map #{route_map}" if route_map
        configure_bgp(cmd)
      end

      ##
      # remove_network removes the instance of a BGP network on the node.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no} shutdown
      #
      # @param prefix [String] The IPv4 prefix to configure as part of
      #   the network statement.  The value must be a valid IPv4 prefix.
      #
      # @param masklen [String] The IPv4 subnet mask length in bits.
      #   The masklen must be in the valid range of 1 to 32.
      #
      # @param route_map [String] The route-map name to apply to the
      #   network statement when configured.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def remove_network(prefix, masklen, route_map = nil)
        cmd = "no network #{prefix}/#{masklen}"
        cmd << " route-map #{route_map}" if route_map
        configure_bgp(cmd)
      end
    end

    ##
    # The BgpNeighbors class implements BGP neighbor configuration
    class BgpNeighbors < Entity
      ##
      # get returns a single BGP neighbor entry from the nodes current
      # configuration.
      #
      # @example
      #   {
      #     peer_group: <string>,
      #     remote_as: <string>,
      #     send_community: <string>,
      #     shutdown: <boolean>,
      #     description: <integer>
      #     next_hop_self: <boolean>
      #     route_map_in: <string>
      #     route_map_out: <string>
      #   }
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [nil, Hash<Symbol, Object>] Returns the BGP neighbor
      #   resource as a Hash.
      def get(name)
        config = get_block('^router bgp .*')
        return nil unless config

        response = parse_peer_group(config, name)
        response.merge!(parse_remote_as(config, name))
        response.merge!(parse_send_community(config, name))
        response.merge!(parse_shutdown(config, name))
        response.merge!(parse_description(config, name))
        response.merge!(parse_next_hop_self(config, name))
        response.merge!(parse_route_map_in(config, name))
        response.merge!(parse_route_map_out(config, name))
        response
      end

      ##
      # getall returns the collection of all neighbor entries for the
      # BGP router instance.
      #
      # @example
      #   {
      #     <name>: {
      #       peer_group: <string>,
      #       remote_as: <string>,
      #       send_community: <string>,
      #       shutdown: <boolean>,
      #       description: <integer>
      #       next_hop_self: <boolean>
      #       route_map_in: <string>
      #       route_map_out: <string>
      #     },
      #     <name>: {
      #       peer_group: <string>,
      #       remote_as: <string>,
      #       send_community: <string>,
      #       shutdown: <boolean>,
      #       description: <integer>
      #       next_hop_self: <boolean>
      #       route_map_in: <string>
      #       route_map_out: <string>
      #     },
      #     ...
      #   }
      #
      # @return [nil, Hash<Symbol, Object>] Returns a hash that
      #   represents the entire BGP neighbor collection from the nodes
      #   running configuration. If there a BGP router is not configured
      #   or contains no neighbor entries then this method will return
      #   an empty hash.
      def getall
        config = get_block('^router bgp .*')
        return nil unless config

        entries = config.scan(/neighbor ([^\s]+)/)
        entries.uniq.each_with_object({}) do |name, hsh|
          resource = get(name[0])
          hsh[name[0]] = resource if resource
        end
      end

      ##
      # parse_peer_group scans the BGP neighbor entries for the
      # peer group.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash attribute.
      def parse_peer_group(config, name)
        value = config.scan(/neighbor #{name} peer-group ([^\s]+)/)
        peer_group = value[0] ? value[0][0] : nil
        { peer_group: peer_group }
      end
      private :parse_peer_group

      ##
      # parse_remote_as scans the BGP neighbor entries for the
      # remote AS.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash attribute
      def parse_remote_as(config, name)
        value = config.scan(/neighbor #{name} remote-as (\d+)/)
        remote_as = value[0] ? value[0][0] : nil
        { remote_as: remote_as }
      end
      private :parse_remote_as

      ##
      # parse_send_community scans the BGP neighbor entries for the
      # remote AS.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash attribute.
      def parse_send_community(config, name)
        value = config.scan(/no neighbor #{name} send-community/)
        enabled = value[0] ? false : true
        { send_community: enabled }
      end
      private :parse_send_community

      ##
      # parse_shutdown scans the BGP neighbor entries for the
      # remote AS.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Resource hash attribute. Returns
      #   true if shutdown, false otherwise.
      def parse_shutdown(config, name)
        value = config.scan(/no neighbor #{name} shutdown/)
        shutdown = value[0] ? false : true
        { shutdown: shutdown }
      end
      private :parse_shutdown

      ##
      # parse_description scans the BGP neighbor entries for the
      # description.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash
      #   attribute.
      def parse_description(config, name)
        value = config.scan(/neighbor #{name} description (.*)$/)
        description = value[0] ? value[0][0] : nil
        { description: description }
      end
      private :parse_description

      ##
      # parse_next_hop_self scans the BGP neighbor entries for the
      # next hop self.
      #
      # @api private
      #
      # @param config [String] The switch config.
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash
      #   attribute.
      def parse_next_hop_self(config, name)
        value = config.scan(/no neighbor #{name} next-hop-self/)
        enabled = value[0] ? false : true
        { next_hop_self: enabled }
      end
      private :parse_next_hop_self

      ##
      # parse_route_map_in scans the BGP neighbor entries for the
      # route map in.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash
      #   attribute.
      def parse_route_map_in(config, name)
        value = config.scan(/neighbor #{name} route-map ([^\s]+) in/)
        route_map_in = value[0] ? value[0][0] : nil
        { route_map_in: route_map_in }
      end
      private :parse_route_map_in

      ##
      # parse_route_map_out scans the BGP neighbor entries for the
      # route map in.
      #
      # @api private
      #
      # @param config [String] The switch config.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Hash<Symbol, Object>] Returns the resource hash
      #   attribute.
      def parse_route_map_out(config, name)
        value = config.scan(/neighbor #{name} route-map ([^\s]+) out/)
        route_map_out = value[0] ? value[0][0] : nil
        { route_map_out: route_map_out }
      end
      private :parse_route_map_out

      ##
      # configure_bgp adds the command to go to BGP config mode.
      # Then it adds the passed in command. The commands are then
      # passed on to configure.
      #
      # @api private
      #
      # @param cmd [String] Command to run under BGP mode.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def configure_bgp(cmd)
        config = get_block('^router bgp .*')
        raise 'BGP router is not configured' unless config
        bgp_as = Bgp.parse_bgp_as(config)
        cmds = ["router bgp #{bgp_as[:bgp_as]}", cmd]
        configure(cmds)
      end
      private :configure_bgp

      ##
      # create will create a new instance of a BGP neighbor on the node.
      # The neighbor is created in the shutdown state and then enabled.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Boolean] Returns true if the command completed successfully.
      def create(name)
        set_shutdown(name, enable: false)
      end

      ##
      # delete will delete the BGP neighbor from the node.
      #
      # ===Commands
      #   no neighbor <name>
      #     or
      #   no neighbor <name> peer-group
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #   This value can be either an IPv4 address or string (in the
      #   case of managing a peer group).
      #
      # @return [Boolean] Returns true if the command completed successfully.
      def delete(name)
        cmd = "no neighbor #{name}"
        response = configure_bgp(cmd)
        unless response
          cmd = "no neighbor #{name} peer-group"
          response = configure_bgp(cmd)
        end
        response
      end

      ##
      # neigh_command_builder for neighbors which calls command_builder.
      #
      # @param name [String] The name of the BGP neighbor to manage.
      #
      # @param cmd [String] The command portion of the neighbor command.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts value [String] Value being set.
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the command using
      #   the default keyword.
      #
      # @return [String] Returns built command string.
      def neigh_command_builder(name, cmd, opts)
        command_builder("neighbor #{name} #{cmd}", opts)
      end

      ##
      # set_peer_group creates a BGP static peer group name.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> peer-group <group-name>
      #
      # @param name [String] The IP address of the neighbor.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts value [String] The group name.
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_peer_group(name, opts = {})
        configure_bgp(neigh_command_builder(name, 'peer-group', opts))
      end

      ##
      # set_remote_as configures the expected AS number for a neighbor
      # (peer).
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> remote-as <as-id>
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts value [String] The remote as-id.
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_remote_as(name, opts = {})
        configure_bgp(neigh_command_builder(name, 'remote-as', opts))
      end

      ##
      # set_shutdown disables the specified neighbor. The value option is
      # not used by this method.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> shutdown
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts enable [String] True enables the specified neighbor.
      #   False disables the specified neighbor.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_shutdown(name, opts = {})
        raise 'set_shutdown has value option set' if opts[:value]
        # Shutdown semantics are opposite of enable semantics so invert enable.
        value = !opts[:enable]
        opts[:enable] = value
        configure_bgp(neigh_command_builder(name, 'shutdown', opts))
      end

      ##
      # set_send_community configures the switch to send community
      # attributes to the specified BGP neighbor. The value option is
      # not used by this method.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> send-community
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts enable [String] True enables the feature. False
      #   disables the feature.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_send_community(name, opts = {})
        raise 'send_community has the value option set' if opts[:value]
        configure_bgp(neigh_command_builder(name, 'send-community', opts))
      end

      ##
      # set_next_hop_self configures the switch to list its address as
      # the next hop in routes that it advertises to the specified
      # BGP-speaking neighbor or neighbors in the specified peer group.
      # The value option is not used by this method.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> next-hop-self
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts enable [String] True enables the feature. False
      #   disables the feature.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_next_hop_self(name, opts = {})
        raise 'set_next_hop_self has the value option set' if opts[:value]
        configure_bgp(neigh_command_builder(name, 'next-hop-self', opts))
      end

      ##
      # set_route_map_in command applies a route map to inbound BGP
      # routes.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> route-map <name> in
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts value [String] Name of a route map.
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_route_map_in(name, opts = {})
        cmd = neigh_command_builder(name, 'route-map', opts) + ' in'
        configure_bgp(cmd)
      end

      ##
      # set_route_map_out command applies a route map to outbound BGP
      # routes.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> route-map <name> out
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts value [String] Name of a route map.
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_route_map_out(name, opts = {})
        cmd = neigh_command_builder(name, 'route-map', opts) + ' out'
        configure_bgp(cmd)
      end

      ##
      # set_description associates descriptive text with the specified
      # peer or peer group.
      #
      # ===Commands
      #   router bgp <bgp_as>
      #     {no | default} neighbor <name> description <string>
      #
      # @param name [String] The IP address or name of the peer group.
      #
      # @param opts [hash] Optional keyword arguments.
      #
      # @option opts value [String] The description string.
      #
      # @option opts enable [Boolean] If false then the command is
      #   negated. Default is true.
      #
      # @option opts default [Boolean] Configure the peer group using
      #   the default keyword.
      #
      # @return [Boolean] Returns true if the command complete successfully.
      def set_description(name, opts = {})
        configure_bgp(neigh_command_builder(name, 'description', opts))
      end
    end
  end
end

redpajama_set_name: RedPajamaGithub


text:
const gulp = require('gulp');

const browserify = require('gulp-browserify');
const babel = require('gulp-babel');
const connect = require('gulp-connect');
const uglify = require('gulp-uglify');
const imagemin = require('gulp-imagemin');
const plumber = require('gulp-plumber');
const notify = require("gulp-notify");
const sourcemaps = require("gulp-sourcemaps");
const gulpIf = require("gulp-if");
const autoprefixer = require("gulp-autoprefixer");

var isDev = !(process.env.DEV == 'production');
var path = {
	root: './',
	build: {
		js: 'dist',
		css: 'dist/css',
		img: 'dist/img'
	},
	src: {
		js: 'src/js/app.js',
		css: 'src/css/*.css',
		img: 'src/img/**/*.*'
	},
	watch: {
		js: 'src/js/**/*.js',
		css: 'src/css/**/*.css',
		img: 'src/img/**/*.*'
	}
};

var errorMessage = () => {
	return plumber({errorHandler: notify.onError((err) => {
		return {
			title: err.name,
			message: err.message
		}
	})})
}

// server
gulp.task('server', () => {
	return connect.server({
		port: 1338,
		livereload: true,
		root: path.root
	});
});

// JavaScript, using Babel and uglifyJS
gulp.task('js', () => {
	return gulp.src(path.src.js)
		.pipe(errorMessage())
		.pipe(browserify({
			debug: isDev
		}))
		.pipe(
			gulpIf(!isDev,
				babel({
					presets: ['es2015']
				})
			)
		)
		.pipe(gulpIf(!isDev, uglify()))
		.pipe(gulp.dest(path.build.js))
		.pipe(connect.reload());
});

// images min
gulp.task('images', function () {
	gulp.src(path.src.img)
		.pipe(errorMessage())
		.pipe(imagemin())
		.pipe(gulp.dest(path.build.img))
		.pipe(connect.reload());
});
gulp.task('css', function () {
	gulp.src(path.src.css)
		.pipe(errorMessage())
		.pipe(autoprefixer())
		.pipe(gulp.dest(path.build.css))
		.pipe(connect.reload());
});

// Watch files
gulp.task('watch', function() {
	gulp.watch(path.watch.js, ['js']);
	gulp.watch(path.watch.img, ['images']);
	gulp.watch(path.watch.css, ['css']);
});

// Tasks
gulp.task('default', ['js', 'css', 'images', 'server', 'watch']);


text:
/**
 * @addtogroup GameActivity Game Activity
 * The interface to use GameActivity.
 * @{
 */

/**
 * @file GameActivity.h
 */

#ifndef ANDROID_GAME_SDK_GAME_ACTIVITY_H
#define ANDROID_GAME_SDK_GAME_ACTIVITY_H

#include <android/asset_manager.h>
#include <android/input.h>
#include <android/native_window.h>
#include <android/rect.h>
#include <jni.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>

#include "game-text-input/gametextinput.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * {@link GameActivityCallbacks}
 */
struct GameActivityCallbacks;

/**
 * This structure defines the native side of an android.app.GameActivity.
 * It is created by the framework, and handed to the application's native
 * code as it is being launched.
 */
typedef struct GameActivity {
    /**
     * Pointer to the callback function table of the native application.
     * You can set the functions here to your own callbacks.  The callbacks
     * pointer itself here should not be changed; it is allocated and managed
     * for you by the framework.
     */
    struct GameActivityCallbacks* callbacks;

    /**
     * The global handle on the process's Java VM.
     */
    JavaVM* vm;

    /**
     * JNI context for the main thread of the app.  Note that this field
     * can ONLY be used from the main thread of the process; that is, the
     * thread that calls into the GameActivityCallbacks.
     */
    JNIEnv* env;

    /**
     * The GameActivity object handle.
     */
    jobject javaGameActivity;

    /**
     * Path to this application's internal data directory.
     */
    const char* internalDataPath;

    /**
     * Path to this application's external (removable/mountable) data directory.
     */
    const char* externalDataPath;

    /**
     * The platform's SDK version code.
     */
    int32_t sdkVersion;

    /**
     * This is the native instance of the application.  It is not used by
     * the framework, but can be set by the application to its own instance
     * state.
     */
    void* instance;

    /**
     * Pointer to the Asset Manager instance for the application.  The
     * application uses this to access binary assets bundled inside its own .apk
     * file.
     */
    AAssetManager* assetManager;

    /**
     * Available starting with Honeycomb: path to the directory containing
     * the application's OBB files (if any).  If the app doesn't have any
     * OBB files, this directory may not exist.
     */
    const char* obbPath;
} GameActivity;

/**
 * The maximum number of axes supported in an Android MotionEvent.
 * See https://developer.android.com/ndk/reference/group/input.
 */
#define GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT 48

/**
 * \brief Describe information about a pointer, found in a
 * GameActivityMotionEvent.
 *
 * You can read values directly from this structure, or use helper functions
 * (`GameActivityPointerAxes_getX`, `GameActivityPointerAxes_getY` and
 * `GameActivityPointerAxes_getAxisValue`).
 *
 * The X axis and Y axis are enabled by default but any other axis that you want
 * to read **must** be enabled first, using
 * `GameActivityPointerAxes_enableAxis`.
 *
 * \see GameActivityMotionEvent
 */
typedef struct GameActivityPointerAxes {
    int32_t id;
    float axisValues[GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT];
    float rawX;
    float rawY;
} GameActivityPointerAxes;

/** \brief Get the current X coordinate of the pointer. */
inline float GameActivityPointerAxes_getX(
    const GameActivityPointerAxes* pointerInfo) {
    return pointerInfo->axisValues[AMOTION_EVENT_AXIS_X];
}

/** \brief Get the current Y coordinate of the pointer. */
inline float GameActivityPointerAxes_getY(
    const GameActivityPointerAxes* pointerInfo) {
    return pointerInfo->axisValues[AMOTION_EVENT_AXIS_Y];
}

/**
 * \brief Enable the specified axis, so that its value is reported in the
 * GameActivityPointerAxes structures stored in a motion event.
 *
 * You must enable any axis that you want to read, apart from
 * `AMOTION_EVENT_AXIS_X` and `AMOTION_EVENT_AXIS_Y` that are enabled by
 * default.
 *
 * If the axis index is out of range, nothing is done.
 */
void GameActivityPointerAxes_enableAxis(int32_t axis);

/**
 * \brief Disable the specified axis. Its value won't be reported in the
 * GameActivityPointerAxes structures stored in a motion event anymore.
 *
 * Apart from X and Y, any axis that you want to read **must** be enabled first,
 * using `GameActivityPointerAxes_enableAxis`.
 *
 * If the axis index is out of range, nothing is done.
 */
void GameActivityPointerAxes_disableAxis(int32_t axis);

/**
 * \brief Get the value of the requested axis.
 *
 * Apart from X and Y, any axis that you want to read **must** be enabled first,
 * using `GameActivityPointerAxes_enableAxis`.
 *
 * Find the valid enums for the axis (`AMOTION_EVENT_AXIS_X`,
 * `AMOTION_EVENT_AXIS_Y`, `AMOTION_EVENT_AXIS_PRESSURE`...)
 * in https://developer.android.com/ndk/reference/group/input.
 *
 * @param pointerInfo The structure containing information about the pointer,
 * obtained from GameActivityMotionEvent.
 * @param axis The axis to get the value from
 * @return The value of the axis, or 0 if the axis is invalid or was not
 * enabled.
 */
inline float GameActivityPointerAxes_getAxisValue(
    GameActivityPointerAxes* pointerInfo, int32_t axis) {
    if (axis < 0 || axis >= GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT) {
        return 0;
    }

    return pointerInfo->axisValues[axis];
}

/**
 * The maximum number of pointers returned inside a motion event.
 */
#if (defined GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT_OVERRIDE)
#define GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT \
    GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT_OVERRIDE
#else
#define GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT 8
#endif

/**
 * \brief Describe a motion event that happened on the GameActivity SurfaceView.
 *
 * This is 1:1 mapping to the information contained in a Java `MotionEvent`
 * (see https://developer.android.com/reference/android/view/MotionEvent).
 */
typedef struct GameActivityMotionEvent {
    int32_t deviceId;
    int32_t source;
    int32_t action;

    int64_t eventTime;
    int64_t downTime;

    int32_t flags;
    int32_t metaState;

    int32_t actionButton;
    int32_t buttonState;
    int32_t classification;
    int32_t edgeFlags;

    uint32_t pointerCount;
    GameActivityPointerAxes
        pointers[GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT];

    float precisionX;
    float precisionY;
} GameActivityMotionEvent;

/**
 * \brief Describe a key event that happened on the GameActivity SurfaceView.
 *
 * This is 1:1 mapping to the information contained in a Java `KeyEvent`
 * (see https://developer.android.com/reference/android/view/KeyEvent).
 */
typedef struct GameActivityKeyEvent {
    int32_t deviceId;
    int32_t source;
    int32_t action;

    int64_t eventTime;
    int64_t downTime;

    int32_t flags;
    int32_t metaState;

    int32_t modifiers;
    int32_t repeatCount;
    int32_t keyCode;
    int32_t unicodeChar;
} GameActivityKeyEvent;

/**
 * A function the user should call from their callback with the data, its length
 * and the library- supplied context.
 */
typedef void (*SaveInstanceStateRecallback)(const char* bytes, int len,
                                            void* context);

/**
 * These are the callbacks the framework makes into a native application.
 * All of these callbacks happen on the main thread of the application.
 * By default, all callbacks are NULL; set to a pointer to your own function
 * to have it called.
 */
typedef struct GameActivityCallbacks {
    /**
     * GameActivity has started.  See Java documentation for Activity.onStart()
     * for more information.
     */
    void (*onStart)(GameActivity* activity);

    /**
     * GameActivity has resumed.  See Java documentation for Activity.onResume()
     * for more information.
     */
    void (*onResume)(GameActivity* activity);

    /**
     * The framework is asking GameActivity to save its current instance state.
     * See the Java documentation for Activity.onSaveInstanceState() for more
     * information. The user should call the recallback with their data, its
     * length and the provided context; they retain ownership of the data. Note
     * that the saved state will be persisted, so it can not contain any active
     * entities (pointers to memory, file descriptors, etc).
     */
    void (*onSaveInstanceState)(GameActivity* activity,
                                SaveInstanceStateRecallback recallback,
                                void* context);

    /**
     * GameActivity has paused.  See Java documentation for Activity.onPause()
     * for more information.
     */
    void (*onPause)(GameActivity* activity);

    /**
     * GameActivity has stopped.  See Java documentation for Activity.onStop()
     * for more information.
     */
    void (*onStop)(GameActivity* activity);

    /**
     * GameActivity is being destroyed.  See Java documentation for
     * Activity.onDestroy() for more information.
     */
    void (*onDestroy)(GameActivity* activity);

    /**
     * Focus has changed in this GameActivity's window.  This is often used,
     * for example, to pause a game when it loses input focus.
     */
    void (*onWindowFocusChanged)(GameActivity* activity, bool hasFocus);

    /**
     * The drawing window for this native activity has been created.  You
     * can use the given native window object to start drawing.
     */
    void (*onNativeWindowCreated)(GameActivity* activity,
                                  ANativeWindow* window);

    /**
     * The drawing window for this native activity has been resized.  You should
     * retrieve the new size from the window and ensure that your rendering in
     * it now matches.
     */
    void (*onNativeWindowResized)(GameActivity* activity, ANativeWindow* window,
                                  int32_t newWidth, int32_t newHeight);

    /**
     * The drawing window for this native activity needs to be redrawn.  To
     * avoid transient artifacts during screen changes (such resizing after
     * rotation), applications should not return from this function until they
     * have finished drawing their window in its current state.
     */
    void (*onNativeWindowRedrawNeeded)(GameActivity* activity,
                                       ANativeWindow* window);

    /**
     * The drawing window for this native activity is going to be destroyed.
     * You MUST ensure that you do not touch the window object after returning
     * from this function: in the common case of drawing to the window from
     * another thread, that means the implementation of this callback must
     * properly synchronize with the other thread to stop its drawing before
     * returning from here.
     */
    void (*onNativeWindowDestroyed)(GameActivity* activity,
                                    ANativeWindow* window);

    /**
     * The current device AConfiguration has changed.  The new configuration can
     * be retrieved from assetManager.
     */
    void (*onConfigurationChanged)(GameActivity* activity);

    /**
     * The system is running low on memory.  Use this callback to release
     * resources you do not need, to help the system avoid killing more
     * important processes.
     */
    void (*onTrimMemory)(GameActivity* activity, int level);

    /**
     * Callback called for every MotionEvent done on the GameActivity
     * SurfaceView. Ownership of `event` is maintained by the library and it is
     * only valid during the callback.
     */
    bool (*onTouchEvent)(GameActivity* activity,
                         const GameActivityMotionEvent* event);

    /**
     * Callback called for every key down event on the GameActivity SurfaceView.
     * Ownership of `event` is maintained by the library and it is only valid
     * during the callback.
     */
    bool (*onKeyDown)(GameActivity* activity,
                      const GameActivityKeyEvent* event);

    /**
     * Callback called for every key up event on the GameActivity SurfaceView.
     * Ownership of `event` is maintained by the library and it is only valid
     * during the callback.
     */
    bool (*onKeyUp)(GameActivity* activity, const GameActivityKeyEvent* event);

    /**
     * Callback called for every soft-keyboard text input event.
     * Ownership of `state` is maintained by the library and it is only valid
     * during the callback.
     */
    void (*onTextInputEvent)(GameActivity* activity,
                             const GameTextInputState* state);

    /**
     * Callback called when WindowInsets of the main app window have changed.
     * Call GameActivity_getWindowInsets to retrieve the insets themselves.
     */
    void (*onWindowInsetsChanged)(GameActivity* activity);
} GameActivityCallbacks;

/**
 * \brief Convert a Java `MotionEvent` to a `GameActivityMotionEvent`.
 *
 * This is done automatically by the GameActivity: see `onTouchEvent` to set
 * a callback to consume the received events.
 * This function can be used if you re-implement events handling in your own
 * activity.
 * Ownership of out_event is maintained by the caller.
 */
void GameActivityMotionEvent_fromJava(JNIEnv* env, jobject motionEvent,
                                      GameActivityMotionEvent* out_event);

/**
 * \brief Convert a Java `KeyEvent` to a `GameActivityKeyEvent`.
 *
 * This is done automatically by the GameActivity: see `onKeyUp` and `onKeyDown`
 * to set a callback to consume the received events.
 * This function can be used if you re-implement events handling in your own
 * activity.
 * Ownership of out_event is maintained by the caller.
 */
void GameActivityKeyEvent_fromJava(JNIEnv* env, jobject motionEvent,
                                   GameActivityKeyEvent* out_event);

/**
 * This is the function that must be in the native code to instantiate the
 * application's native activity.  It is called with the activity instance (see
 * above); if the code is being instantiated from a previously saved instance,
 * the savedState will be non-NULL and point to the saved data.  You must make
 * any copy of this data you need -- it will be released after you return from
 * this function.
 */
typedef void GameActivity_createFunc(GameActivity* activity, void* savedState,
                                     size_t savedStateSize);

/**
 * The name of the function that NativeInstance looks for when launching its
 * native code.  This is the default function that is used, you can specify
 * "android.app.func_name" string meta-data in your manifest to use a different
 * function.
 */
extern GameActivity_createFunc GameActivity_onCreate;

/**
 * Finish the given activity.  Its finish() method will be called, causing it
 * to be stopped and destroyed.  Note that this method can be called from
 * *any* thread; it will send a message to the main thread of the process
 * where the Java finish call will take place.
 */
void GameActivity_finish(GameActivity* activity);

/**
 * Flags for GameActivity_setWindowFlags,
 * as per the Java API at android.view.WindowManager.LayoutParams.
 */
enum GameActivitySetWindowFlags {
    /**
     * As long as this window is visible to the user, allow the lock
     * screen to activate while the screen is on.  This can be used
     * independently, or in combination with {@link
     * GAMEACTIVITY_FLAG_KEEP_SCREEN_ON} and/or {@link
     * GAMEACTIVITY_FLAG_SHOW_WHEN_LOCKED}
     */
    GAMEACTIVITY_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
    /** Everything behind this window will be dimmed. */
    GAMEACTIVITY_FLAG_DIM_BEHIND = 0x00000002,
    /**
     * Blur everything behind this window.
     * @deprecated Blurring is no longer supported.
     */
    GAMEACTIVITY_FLAG_BLUR_BEHIND = 0x00000004,
    /**
     * This window won't ever get key input focus, so the
     * user can not send key or other button events to it.  Those will
     * instead go to whatever focusable window is behind it.  This flag
     * will also enable {@link GAMEACTIVITY_FLAG_NOT_TOUCH_MODAL} whether or not
     * that is explicitly set.
     *
     * Setting this flag also implies that the window will not need to
     * interact with
     * a soft input method, so it will be Z-ordered and positioned
     * independently of any active input method (typically this means it
     * gets Z-ordered on top of the input method, so it can use the full
     * screen for its content and cover the input method if needed.  You
     * can use {@link GAMEACTIVITY_FLAG_ALT_FOCUSABLE_IM} to modify this
     * behavior.
     */
    GAMEACTIVITY_FLAG_NOT_FOCUSABLE = 0x00000008,
    /** This window can never receive touch events. */
    GAMEACTIVITY_FLAG_NOT_TOUCHABLE = 0x00000010,
    /**
     * Even when this window is focusable (its
     * {@link GAMEACTIVITY_FLAG_NOT_FOCUSABLE} is not set), allow any pointer
     * events outside of the window to be sent to the windows behind it.
     * Otherwise it will consume all pointer events itself, regardless of
     * whether they are inside of the window.
     */
    GAMEACTIVITY_FLAG_NOT_TOUCH_MODAL = 0x00000020,
    /**
     * When set, if the device is asleep when the touch
     * screen is pressed, you will receive this first touch event.  Usually
     * the first touch event is consumed by the system since the user can
     * not see what they are pressing on.
     *
     * @deprecated This flag has no effect.
     */
    GAMEACTIVITY_FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
    /**
     * As long as this window is visible to the user, keep
     * the device's screen turned on and bright.
     */
    GAMEACTIVITY_FLAG_KEEP_SCREEN_ON = 0x00000080,
    /**
     * Place the window within the entire screen, ignoring
     * decorations around the border (such as the status bar).  The
     * window must correctly position its contents to take the screen
     * decoration into account.
     */
    GAMEACTIVITY_FLAG_LAYOUT_IN_SCREEN = 0x00000100,
    /** Allows the window to extend outside of the screen. */
    GAMEACTIVITY_FLAG_LAYOUT_NO_LIMITS = 0x00000200,
    /**
     * Hide all screen decorations (such as the status
     * bar) while this window is displayed.  This allows the window to
     * use the entire display space for itself -- the status bar will
     * be hidden when an app window with this flag set is on the top
     * layer. A fullscreen window will ignore a value of {@link
     * GAMEACTIVITY_SOFT_INPUT_ADJUST_RESIZE}; the window will stay
     * fullscreen and will not resize.
     */
    GAMEACTIVITY_FLAG_FULLSCREEN = 0x00000400,
    /**
     * Override {@link GAMEACTIVITY_FLAG_FULLSCREEN} and force the
     * screen decorations (such as the status bar) to be shown.
     */
    GAMEACTIVITY_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
    /**
     * Turn on dithering when compositing this window to
     * the screen.
     * @deprecated This flag is no longer used.
     */
    GAMEACTIVITY_FLAG_DITHER = 0x00001000,
    /**
     * Treat the content of the window as secure, preventing
     * it from appearing in screenshots or from being viewed on non-secure
     * displays.
     */
    GAMEACTIVITY_FLAG_SECURE = 0x00002000,
    /**
     * A special mode where the layout parameters are used
     * to perform scaling of the surface when it is composited to the
     * screen.
     */
    GAMEACTIVITY_FLAG_SCALED = 0x00004000,
    /**
     * Intended for windows that will often be used when the user is
     * holding the screen against their face, it will aggressively
     * filter the event stream to prevent unintended presses in this
     * situation that may not be desired for a particular window, when
     * such an event stream is detected, the application will receive
     * a {@link AMOTION_EVENT_ACTION_CANCEL} to indicate this so
     * applications can handle this accordingly by taking no action on
     * the event until the finger is released.
     */
    GAMEACTIVITY_FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
    /**
     * A special option only for use in combination with
     * {@link GAMEACTIVITY_FLAG_LAYOUT_IN_SCREEN}.  When requesting layout in
     * the screen your window may appear on top of or behind screen decorations
     * such as the status bar.  By also including this flag, the window
     * manager will report the inset rectangle needed to ensure your
     * content is not covered by screen decorations.
     */
    GAMEACTIVITY_FLAG_LAYOUT_INSET_DECOR = 0x00010000,
    /**
     * Invert the state of {@link GAMEACTIVITY_FLAG_NOT_FOCUSABLE} with
     * respect to how this window interacts with the current method.
     * That is, if FLAG_NOT_FOCUSABLE is set and this flag is set,
     * then the window will behave as if it needs to interact with the
     * input method and thus be placed behind/away from it; if {@link
     * GAMEACTIVITY_FLAG_NOT_FOCUSABLE} is not set and this flag is set,
     * then the window will behave as if it doesn't need to interact
     * with the input method and can be placed to use more space and
     * cover the input method.
     */
    GAMEACTIVITY_FLAG_ALT_FOCUSABLE_IM = 0x00020000,
    /**
     * If you have set {@link GAMEACTIVITY_FLAG_NOT_TOUCH_MODAL}, you
     * can set this flag to receive a single special MotionEvent with
     * the action
     * {@link AMOTION_EVENT_ACTION_OUTSIDE} for
     * touches that occur outside of your window.  Note that you will not
     * receive the full down/move/up gesture, only the location of the
     * first down as an {@link AMOTION_EVENT_ACTION_OUTSIDE}.
     */
    GAMEACTIVITY_FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
    /**
     * Special flag to let windows be shown when the screen
     * is locked. This will let application windows take precedence over
     * key guard or any other lock screens. Can be used with
     * {@link GAMEACTIVITY_FLAG_KEEP_SCREEN_ON} to turn screen on and display
     * windows directly before showing the key guard window.  Can be used with
     * {@link GAMEACTIVITY_FLAG_DISMISS_KEYGUARD} to automatically fully
     * dismisss non-secure keyguards.  This flag only applies to the top-most
     * full-screen window.
     */
    GAMEACTIVITY_FLAG_SHOW_WHEN_LOCKED = 0x00080000,
    /**
     * Ask that the system wallpaper be shown behind
     * your window.  The window surface must be translucent to be able
     * to actually see the wallpaper behind it; this flag just ensures
     * that the wallpaper surface will be there if this window actually
     * has translucent regions.
     */
    GAMEACTIVITY_FLAG_SHOW_WALLPAPER = 0x00100000,
    /**
     * When set as a window is being added or made
     * visible, once the window has been shown then the system will
     * poke the power manager's user activity (as if the user had woken
     * up the device) to turn the screen on.
     */
    GAMEACTIVITY_FLAG_TURN_SCREEN_ON = 0x00200000,
    /**
     * When set the window will cause the keyguard to
     * be dismissed, only if it is not a secure lock keyguard.  Because such
     * a keyguard is not needed for security, it will never re-appear if
     * the user navigates to another window (in contrast to
     * {@link GAMEACTIVITY_FLAG_SHOW_WHEN_LOCKED}, which will only temporarily
     * hide both secure and non-secure keyguards but ensure they reappear
     * when the user moves to another UI that doesn't hide them).
     * If the keyguard is currently active and is secure (requires an
     * unlock pattern) than the user will still need to confirm it before
     * seeing this window, unless {@link GAMEACTIVITY_FLAG_SHOW_WHEN_LOCKED} has
     * also been set.
     */
    GAMEACTIVITY_FLAG_DISMISS_KEYGUARD = 0x00400000,
};

/**
 * Change the window flags of the given activity.  Calls getWindow().setFlags()
 * of the given activity.
 * Note that some flags must be set before the window decoration is created,
 * see
 * https://developer.android.com/reference/android/view/Window#setFlags(int,%20int).
 * Note also that this method can be called from
 * *any* thread; it will send a message to the main thread of the process
 * where the Java finish call will take place.
 */
void GameActivity_setWindowFlags(GameActivity* activity, uint32_t addFlags,
                                 uint32_t removeFlags);

/**
 * Flags for GameActivity_showSoftInput; see the Java InputMethodManager
 * API for documentation.
 */
enum GameActivityShowSoftInputFlags {
    /**
     * Implicit request to show the input window, not as the result
     * of a direct request by the user.
     */
    GAMEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT = 0x0001,

    /**
     * The user has forced the input method open (such as by
     * long-pressing menu) so it should not be closed until they
     * explicitly do so.
     */
    GAMEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002,
};

/**
 * Show the IME while in the given activity.  Calls
 * InputMethodManager.showSoftInput() for the given activity.  Note that this
 * method can be called from *any* thread; it will send a message to the main
 * thread of the process where the Java call will take place.
 */
void GameActivity_showSoftInput(GameActivity* activity, uint32_t flags);

/**
 * Set the text entry state (see documentation of the GameTextInputState struct
 * in the Game Text Input library reference).
 *
 * Ownership of the state is maintained by the caller.
 */
void GameActivity_setTextInputState(GameActivity* activity,
                                    const GameTextInputState* state);

/**
 * Get the last-received text entry state (see documentation of the
 * GameTextInputState struct in the Game Text Input library reference).
 *
 */
void GameActivity_getTextInputState(GameActivity* activity,
                                    GameTextInputGetStateCallback callback,
                                    void* context);

/**
 * Get a pointer to the GameTextInput library instance.
 */
GameTextInput* GameActivity_getTextInput(const GameActivity* activity);

/**
 * Flags for GameActivity_hideSoftInput; see the Java InputMethodManager
 * API for documentation.
 */
enum GameActivityHideSoftInputFlags {
    /**
     * The soft input window should only be hidden if it was not
     * explicitly shown by the user.
     */
    GAMEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY = 0x0001,
    /**
     * The soft input window should normally be hidden, unless it was
     * originally shown with {@link GAMEACTIVITY_SHOW_SOFT_INPUT_FORCED}.
     */
    GAMEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002,
};

/**
 * Hide the IME while in the given activity.  Calls
 * InputMethodManager.hideSoftInput() for the given activity.  Note that this
 * method can be called from *any* thread; it will send a message to the main
 * thread of the process where the Java finish call will take place.
 */
void GameActivity_hideSoftInput(GameActivity* activity, uint32_t flags);

/**
 * Get the current window insets of the particular component. See
 * https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat.Type
 * for more details.
 * You can use these insets to influence what you show on the screen.
 */
void GameActivity_getWindowInsets(GameActivity* activity,
                                  GameCommonInsetsType type, ARect* insets);

/**
 * Set options on how the IME behaves when it is requested for text input.
 * See
 * https://developer.android.com/reference/android/view/inputmethod/EditorInfo
 * for the meaning of inputType, actionId and imeOptions.
 *
 * Note that this function will attach the current thread to the JVM if it is
 * not already attached, so the caller must detach the thread from the JVM
 * before the thread is destroyed using DetachCurrentThread.
 */
void GameActivity_setImeEditorInfo(GameActivity* activity, int inputType,
                                   int actionId, int imeOptions);

#ifdef __cplusplus
}
#endif

/** @} */

#endif  // ANDROID_GAME_SDK_GAME_ACTIVITY_H


text:
package com.emmasuzuki.espressospoondemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

/**
 * Demo Login activity class
 */
public class LoginActivity extends Activity {

    private static final String DEMO_EMAIL = "espresso@spoon.com";
    private static final String DEMO_PASSWORD = "lemoncake";

    private EditText mEmail, mPassword;
    private View mError;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);

        mEmail = (EditText) findViewById(R.id.email);
        mPassword = (EditText) findViewById(R.id.password);

        View submitButton = findViewById(R.id.submit);
        submitButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                validateFields();

                if (mEmail.getError() == null && mPassword.getError() == null) {
                    validateAccount();
                }
            }
        });
    }

    private void validateFields() {
        if (!android.util.Patterns.EMAIL_ADDRESS.matcher(mEmail.getText().toString()).matches()) {
            mEmail.setError(getString(R.string.msg_email_error));
        } else {
            mEmail.setError(null);
        }

        if (mPassword.getText().toString().isEmpty()) {
            mPassword.setError(getString(R.string.msg_password_error));
        } else {
            mPassword.setError(null);
        }
    }

    private void validateAccount() {
        if (!mEmail.getText().toString().equals(DEMO_EMAIL) || !mPassword.getText().toString().equals(DEMO_PASSWORD)) {
            if (mError == null) {
                mError = findViewById(R.id.error);
            }

            // Purposefully commenting this line out to demonstrate test failure
//            mError.setVisibility(View.VISIBLE);
        } else {
            mError.setVisibility(View.GONE);
        }
    }
}


text:
            <?php $this->load->view('site/common/admin_menu'); ?>

                    <?php
                        if($this->session->has_userdata('suc_msg')){
                            echo message_alert($this->session->userdata('suc_msg'), 2);
                            $this->session->unset_userdata('suc_msg');
                        }
                        if($this->session->has_userdata('err_msg')){
                            echo message_alert($this->session->userdata('err_msg'), 4);
                            $this->session->unset_userdata('err_msg');
                        }
                    ?>
                    <?php echo (isset($error) && $error == 'update_email_form')? validation_errors() : ''; ?>

Change Email

                        <form class="form-horizontal" action="settings" name="change_email" id="change_email" method="POST">

                                Email of organization

                                    <input type="email" required class="form-control" id="user_email" ng-model="user_email" ng-init="user_email = '<?php echo $user_email; ?>'" name="user_email" placeholder="Email Address" value="<?php echo set_value('user_email', $user_email); ?>">

                                        Organization email is required.
                                        Please provide a valid email.

                                    <button type="submit" class="btn btn-danger btn-submit" value="Submit" name="update_email" ng-disabled="change_email.user_email.$dirty && change_email.user_email.$invalid">Submit </button>

                        </form>

                    <?php
                        if($this->session->has_userdata('pass_suc_msg')){
                            echo message_alert($this->session->userdata('pass_suc_msg'), 2);
                            $this->session->unset_userdata('pass_suc_msg');
                        }
                        if($this->session->has_userdata('pass_err_msg')){
                            echo message_alert($this->session->userdata('pass_err_msg'), 4);
                            $this->session->unset_userdata('pass_err_msg');
                        }
                    ?>

Change Password

                        <?php echo (isset($error) && $error == 'update_pass_form')? validation_errors() : ''; ?>
                        <form class="form-horizontal" action="settings" name="change_password" id="change_password" method="POST">

                                Current Password

                                    <input type="password" required class="form-control" id="cur_pass" name="cur_pass" placeholder="Current Password">

                                New Password

                                    <input type="password" required class="form-control" id="new_pass" name="new_pass" placeholder="New Password">

                                Confirm Password

                                    <input type="password" required class="form-control" id="con_pass" name="con_pass" placeholder="Confirm Password">

                                    <button type="submit" class="btn btn-danger btn-submit" value="Submit" name="update_pass">Submit </button>

                        </form>


text:
app.controller('SatisDynamiqueCtrl', function($scope, $http, $modal, SatisDynamique) {

    $scope.packages = [];
    $scope.repositories = [];
    $scope.allPackagesInformations = "";
    $scope.alerts = [];
    $scope.repositoryType = [
        {value: "package", text: 'package'},
        {value: "git", text: 'git'},
        {value: 'vcs', text: 'vcs'},
        {value: 'hg', text: 'hg'},
        {value: 'composer', text: 'composer'}
    ];

    $scope.repositoryInserted = [];

    $scope.loadPackage = function() {
        SatisDynamique.allPakage().get().$promise.then(function(p){
            $scope.packages = p.packages;
        },function(data, status, headers, config) {
            $scope.alerts.push({type:'danger', msg:angular.fromJson(data.data)});
        });
    };

    $scope.loadRepositories = function() {
        SatisDynamique.allRepositories().get().$promise.then(function(p){
            $scope.repositories = p.repositories;
        },function(data, status, headers, config) {
            $scope.alerts.push({type:'danger', msg:angular.fromJson(data.data)});
        });
    };

    $scope.loadPackage();
    $scope.loadRepositories();

    $scope.detach = function(obj)
    {
        return angular.copy(obj);
    };

    $scope.updatePackage = function(newPackage, oldPackage) {

        if(newPackage.hasOwnProperty("isNew") && newPackage.isNew == true) {
            delete newPackage['isNew'];
            var package = {package:newPackage};
        } else {
            var package = {package:{old:oldPackage, new:newPackage}};
        }

        return SatisDynamique.postPakage()
                .save(package)
                .$promise.then(function(){
                    $scope.alerts.push({type:'success', msg:'The package have been well saved'});
                    $scope.loadPackage();
                    return true;
                }, function(data, status, headers, config) {
                    $scope.alerts.push({type:'danger', msg:angular.fromJson(data.data)});
                    return false;
                });
    };

    $scope.addNewPackage = function() {
        $scope.inserted = {
            name: '',
            version: '',
            isNew: 'true'
        };
        $scope.packages.unshift($scope.inserted);
    };

    $scope.remove = function(index, item, type) {

        var modalInstance = $modal.open({
            templateUrl: 'removeModal.html',
            controller: ModalInstanceCtrl,
            resolve: {
                index: function() {
                    return index;
                },
                item: function() {
                    return item;
                },
                type: function() {
                    return type;
                }
            }
        });

        modalInstance.result.then(function(index) {
            if(index != undefined) {

                if(type == "package") {
                    $scope.packages.splice(index, 1);
                    var requestProvider = SatisDynamique.postPakage();
                    var data = {package:item};
                } else if (type == "repository") {
                    $scope.repositories.splice(index, 1);
                    var requestProvider = SatisDynamique.postRepository();
                    var data = {repository:item};
                }

                if(!item.hasOwnProperty("isNew") || item.isNew == false) {
                    requestProvider.remove(data)
                    .$promise.then(function(p){
                        $scope.alerts.push({type:'success', msg:'The package have been well removed'});
                        return true;
                    }, function(data, status, headers, config) {
                        $scope.alerts.push({type:'danger', msg:angular.fromJson(data.data)});
                        return false;
                    });
                }
            }
        });
    };

    $scope.updateRepository = function(newRepository, oldRepository) {

        newRepository = app.recomposeJsonFromFlat(newRepository);

        if(newRepository.hasOwnProperty("isNew") && newRepository.isNew == true) {
            delete newRepository['isNew'];
            var package = newRepository;
        } else {
            var package = {repository:{old:oldRepository, new:newRepository.repository}};
        }

        return SatisDynamique.postRepository()
                .save(package)
                .$promise.then(function(){
                    $scope.alerts.push({type:'success', msg:'The repository have been well saved'});
                    $scope.loadRepositories();
                    return true;
                }, function(data, status, headers, config) {
                    $scope.alerts.push({type:'danger', msg:angular.fromJson(data.data)});
                    return false;
                });
        ;
    };

    $scope.cancelRepository = function(repository) {
        if(repository.hasOwnProperty("rollback")) {
           repository.rollback();
           delete repository["rollback"];
        }
    };

    $scope.addNewRepository = function() {
        $scope.repositoryInserted = {
            type: 'git',
            url: '',
            isNew: 'true'
        };
        $scope.repositories.unshift($scope.repositoryInserted);
    };

    $scope.changeRepositoryType = function ($data, repository)
    {
        oldRepositoryType = repository.type;
        repository.rollback = function() {
            repository.type = oldRepositoryType;
        }

        repository.type = $data;
    };

    $scope.closeAlert = function(index) {
        $scope.alerts.splice(index, 1);
    };

    $scope.retriveAllPackagesInfos = function()
    {
        SatisDynamique.allPakagesInformations().get().$promise.then(
                function(data, status, headers, config){
                    $scope.allPackagesInformations = data.all;
        },function(data, status, headers, config) {
            $scope.alerts.push({type:'danger', msg:angular.fromJson(data.data)});
        });
    };
});

var ModalInstanceCtrl = function($scope, $modalInstance, index, item) {

    $scope.item = item;

    $scope.ok = function() {
        $modalInstance.close(index);
    };

    $scope.cancel = function() {
        $modalInstance.close();
    };
};