public class BookingSearchResultsActivity extends AppCompatActivity {

    public final static String BOOKING_SEARCH_RESULT_SERIALIZED_KEY = "booking_search_result_serialized";

    @Bind(R.id.vehicle_list)
    protected ListView vehicleListView;

    private CarRentalApiClient apiClient = CarRentalApiClientFactory.getApiClient();
    private BookingSearchResultListAdapter bookingSearchResultListAdapter;
    private SearchAvailableVehiclesRequestContract searchAvailableVehiclesRequestContract;
    private BranchContract branchContract = PreferencesManager.getCurrentBranch(this);

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

        searchAvailableVehiclesRequestContract = new SearchAvailableVehiclesRequestContract();
        Bundle bundle = getIntent().getExtras();
        searchAvailableVehiclesRequestContract.pickupDate = bundle.getString(SearchAvailableVehicleActivity.PICKUP_DATE_KEY);
        searchAvailableVehiclesRequestContract.returnDate = bundle.getString(SearchAvailableVehicleActivity.RETURN_DATE_KEY);
        searchAvailableVehiclesRequestContract.vehicleType = bundle.getInt(SearchAvailableVehicleActivity.VEHICLE_TYPE_KEY);

        ButterKnife.bind(this);
        ActivityUtils.buildDrawer(this);

        if (branchContract == null) {
            Toast toast = Toast.makeText(BookingSearchResultsActivity.this, getString(R.string.invalid_branch), Toast.LENGTH_SHORT);
            toast.show();
            return;
        } else {
            setTitle(String.format(getString(R.string.booking_search_results_title_formatted), branchContract.name));
        }

        List<BookingSearchResultContract> bookingSearchResults = new ArrayList<>();

        bookingSearchResultListAdapter = new BookingSearchResultListAdapter(this, bookingSearchResults);

        vehicleListView.setAdapter(bookingSearchResultListAdapter);

        //Opening app
        if (PreferencesManager.isLoggedIn(BookingSearchResultsActivity.this)) {
            if (PreferencesManager.isStaffUser(BookingSearchResultsActivity.this)) {
                vehicleListView.setClickable(true);
                vehicleListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        BookingSearchResultContract selectedBooking = bookingSearchResultListAdapter.getItem(position);
                        Intent intent = new Intent(getBaseContext(), ChooseUserForBookingActivity.class);
                        intent.putExtra(BOOKING_SEARCH_RESULT_SERIALIZED_KEY, SerializationUtils.serialize(selectedBooking));
                        startActivity(intent);
                    }
                });
            } else {
                vehicleListView.setClickable(true);
                vehicleListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        BookingSearchResultContract selectedBooking = bookingSearchResultListAdapter.getItem(position);
                        Intent intent = new Intent(getBaseContext(), BookVehicleActivity.class);
                        intent.putExtra(BOOKING_SEARCH_RESULT_SERIALIZED_KEY, SerializationUtils.serialize(selectedBooking));
                        startActivity(intent);
                    }
                });
            }
        } else {
            vehicleListView.setClickable(true);
            vehicleListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast toast = Toast.makeText(BookingSearchResultsActivity.this, R.string.login_register_required_book_vehicle, Toast.LENGTH_SHORT);
                    toast.show();
                }
            });
        }

        new GetVehiclesTask().start();
    }


//############################## TASKS #############################################################

    private class GetVehiclesTask extends AsyncTask<Void, Void, List<BookingSearchResultContract>> {

        ProgressDialog progressDialog;
        Exception apiException;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog = new ProgressDialog(BookingSearchResultsActivity.this);
            progressDialog.setMessage(getString(R.string.loading_text));
            progressDialog.setIndeterminate(false);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progressDialog.setCancelable(true);
            progressDialog.show();
        }

        @Override
        protected List<BookingSearchResultContract> doInBackground(Void... params) {
            try {
                return apiClient.searchAvailableVehicles(searchAvailableVehiclesRequestContract);
            } catch (Exception e) {
                apiException = e;
                return null;
            }
        }

        @Override
        protected void onPostExecute(List<BookingSearchResultContract> result) {
            progressDialog.dismiss();

            if (apiException != null) {
                ActivityUtils.HandleException(BookingSearchResultsActivity.this, apiException);
                return;
            }

            if (result.size() == 0) {
                Toast toast = Toast.makeText(BookingSearchResultsActivity.this, R.string.no_vehicle_found_criteria, Toast.LENGTH_SHORT);
                toast.show();
            }

            bookingSearchResultListAdapter.setVehicles(result);

            progressDialog.dismiss();
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }

        public AsyncTask<Void, Void, List<BookingSearchResultContract>> start(){
            return this.execute();
        }
    }

} public class BookVehicleActivity extends AppCompatActivity {

    //Automatic binding with Butterknife (external library)
    @Bind(R.id.carName)
    protected TextView carName;
    @Bind(R.id.bookingPrice)
    protected TextView bookingPrice;
    @Bind(R.id.carSeats)
    protected TextView carSeats;
    @Bind(R.id.carDoors)
    protected TextView carDoors;
    @Bind(R.id.carTransmission)
    protected TextView carTransmission;
    @Bind(R.id.pickupDate)
    protected TextView pickupDate;
    @Bind(R.id.returnDate)
    protected TextView returnDate;
    @Bind(R.id.creditCardNumberTextField)
    protected EditText creditCardNumberTextField;
    @Bind(R.id.creditCardExpirationMonthTextField)
    protected EditText creditCardExpirationMonthTextField;
    @Bind(R.id.creditCardExpirationYearTextField)
    protected EditText creditCardExpirationYearTextField;
    @Bind(R.id.creditCardCvcCodeTextField)
    protected EditText creditCardCvcCodeTextField;
    @Bind(R.id.userNameField)
    protected TextView userNameField;
    @Bind(R.id.payAndConfirmButton)
    protected Button payAndConfirmButton;

    private DecimalFormat decimalFormat = new DecimalFormat("0.00");
    private BookingSearchResultContract selectedBookingContract;
    private UserContract selectedUserContract;
    private CreateBookingContract createBookingContract;
    private CarRentalApiClient apiClient = CarRentalApiClientFactory.getApiClient();
    private BranchContract branchContract = PreferencesManager.getCurrentBranch(this);

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

        Bundle bundle = getIntent().getExtras();

        selectedBookingContract = SerializationUtils.deserialize(bundle.getString(BookingSearchResultsActivity.BOOKING_SEARCH_RESULT_SERIALIZED_KEY), BookingSearchResultContract.class);

        if (PreferencesManager.isStaffUser(this)) {
            selectedUserContract = SerializationUtils.deserialize(bundle.getString(ChooseUserForBookingActivity.USER_SELECTED_SERIALIZED_KEY), UserContract.class);
        }

        ButterKnife.bind(this);
        ActivityUtils.buildDrawer(this);

        if (branchContract == null) {
            Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_branch, Toast.LENGTH_SHORT);
            toast.show();
            return;
        } else {
            if (PreferencesManager.isStaffUser(this)) {
                setTitle(String.format(getString(R.string.create_booking_title), branchContract.name));
            } else {
                setTitle(String.format(getString(R.string.book_vehicle_title), branchContract.name));
            }
        }

        carName.setText(selectedBookingContract.vehicle.name);
        carSeats.setText(String.format(getString(R.string.seats_number_formatted), selectedBookingContract.vehicle.seats));
        carDoors.setText(String.format(getString(R.string.doors_number_formatted), selectedBookingContract.vehicle.doors));
        carTransmission.setText(selectedBookingContract.vehicle.automaticTransmission ? getString(R.string.automatic_transmission) : getString(R.string.manual_transmission));
        bookingPrice.setText(String.format(getString(R.string.pounds_price), decimalFormat.format(Math.round(selectedBookingContract.price * 100.0) / 100.0)));
        pickupDate.setText(DateUtils.getFormattedDateFromIso8601String(selectedBookingContract.pickupDate));
        returnDate.setText(DateUtils.getFormattedDateFromIso8601String(selectedBookingContract.returnDate));

        if (PreferencesManager.isStaffUser(this)) {
            userNameField.setVisibility(View.VISIBLE);
            userNameField.setText(String.format(getString(R.string.user_formatted), selectedUserContract.fullName));
        }

        payAndConfirmButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createBookingContract = new CreateBookingContract();
                createBookingContract.vehicleId = selectedBookingContract.vehicle.id;
                createBookingContract.vehicleBranchId = selectedBookingContract.vehicle.branch.id;
                createBookingContract.bookingBranchId = branchContract.id;
                createBookingContract.pickupDate = selectedBookingContract.pickupDate;
                createBookingContract.returnDate = selectedBookingContract.returnDate;

                //Card number
                if (creditCardNumberTextField.getText().toString().isEmpty()) {
                    Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_number, Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }
                createBookingContract.creditCardNumber = creditCardNumberTextField.getText().toString();

                //card exp month
                if (creditCardExpirationMonthTextField.getText().toString().isEmpty()) {
                    Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_exp_month, Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }

                try {
                    int month = Integer.decode(creditCardExpirationMonthTextField.getText().toString());

                    if (month < 1 || month > 12) {
                        Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_exp_month, Toast.LENGTH_SHORT);
                        toast.show();
                        return;
                    }
                    createBookingContract.creditCardExpirationMonth = creditCardExpirationMonthTextField.getText().toString();
                } catch (Exception e) {
                    Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_exp_month, Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }


                //card exp year
                if (creditCardExpirationYearTextField.getText().toString().isEmpty()) {
                    Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_exp_year, Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }
                try {
                    Integer.decode(creditCardExpirationYearTextField.getText().toString());
                    createBookingContract.creditCardExpirationYear = creditCardExpirationYearTextField.getText().toString();
                } catch (Exception e) {
                    Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_exp_year, Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }


                //card cvc
                if (creditCardCvcCodeTextField.getText().toString().isEmpty()) {
                    Toast toast = Toast.makeText(BookVehicleActivity.this, R.string.invalid_credit_card_cvc_code, Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }
                createBookingContract.creditCardCvcCode = creditCardCvcCodeTextField.getText().toString();

                if (PreferencesManager.isStaffUser(BookVehicleActivity.this)) {
                    createBookingContract.bookingOwnerUserId = selectedUserContract.id;
                }

                new DoBookVehicleTask().start();
            }
        });
    }


//############################## TASKS #############################################################

    private class DoBookVehicleTask extends AsyncTask<Void, Void, BookingContract> {

        ProgressDialog progressDialog;
        Exception apiException;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog = new ProgressDialog(BookVehicleActivity.this);
            progressDialog.setMessage(getString(R.string.loading_text));
            progressDialog.setIndeterminate(false);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progressDialog.setCancelable(true);
            progressDialog.show();
        }

        @Override
        protected BookingContract doInBackground(Void... params) {
            try {
                return apiClient.bookVehicle(createBookingContract);
            } catch (Exception e) {
                apiException = e;
                return null;
            }
        }

        @Override
        protected void onPostExecute(BookingContract result) {
            Toast toast;

            progressDialog.dismiss();

            if (apiException != null) {
                ActivityUtils.HandleException(BookVehicleActivity.this, apiException);
                return;
            }


            toast = Toast.makeText(BookVehicleActivity.this, R.string.booking_successfully_created, Toast.LENGTH_SHORT);
            toast.show();

            if (PreferencesManager.isStaffUser(BookVehicleActivity.this)) {
                Intent intent = new Intent(getBaseContext(), BranchBookingsActivity.class);
                startActivity(intent);
            } else {
                Intent intent = new Intent(getBaseContext(), UserBookingsActivity.class);
                startActivity(intent);
            }
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }

        public AsyncTask<Void, Void, BookingContract> start(){
            return this.execute();
        }
    }
} public interface CarRentalApiClient {
    /**
     * Return the list of available branches
     *
     * @return list of branches
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<BranchContract> getBranches() throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Return the result of the available vehicles with the given criteria
     *
     * @param contract search criteria
     * @return list of available vehicle results
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<BookingSearchResultContract> searchAvailableVehicles(SearchAvailableVehiclesRequestContract contract) throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Create an user account with the given parameters
     *
     * @param contract account parameters
     * @return created account
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    UserContract createAccount(CreateAccountRequestContract contract) throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Returns the current user account details
     *
     * @return user account details
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    UserContract getAccountDetails() throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Returns the bookings for the current user in the current branch
     *
     * @return list of bookings for the user and branch
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<BookingContract> getUserBookingsForBranch() throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Request a vehicle booking with the given criteria
     *
     * @param contract booking criteria
     * @return created booking
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    BookingContract bookVehicle(CreateBookingContract contract) throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Returns all the bookings for the current branch
     *
     * @return the branch bookings list
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<BookingContract> getBranchBookings() throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Sends a shutdown request to the server
     *
     * @return nothing
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    Void shutdownSystem() throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Create an user account with the given parameters (requires staff level)
     *
     * @param contract the account parameters
     * @return the created account
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    UserContract createUser(CreateAccountRequestContract contract)  throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Create or update a vehicle with the given parameters in the current branch
     *
     * @param contract vehicle parameters
     * @return created or updated vehicle
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    VehicleContract createOrUpdateVehicle(CreateUpdateVehicleContract contract)  throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Search vehicles with the given criteria in the current branch
     *
     * @param contract search criteria
     * @return list of vehicles matching the criteria
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<VehicleContract> searchVehicles(SearchVehicleContract contract)  throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Search users with the given criteria (full text search on email and fullname)
     *
     * @param contract search criteria
     * @return list of users matching the criteria
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<UserContract> searchUser(SearchUserContract contract)  throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Update a booking status with the given parameters
     *
     * @param contract update parameters
     * @return updated booking
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    BookingContract changeBookingStatus(ChangeBookingStatusContract contract)  throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;

    /**
     * Returns the vehicle moves for the current branch matching the filter criteria
     *
     * @param contract filter criteria
     * @return list of bookings requiring moves
     * @throws ApiUnauthorizedException if the request wasn't authenticated or authorized
     * @throws ApiException if there was a general error during the request
     * @throws ApiInvalidParameterException if there was an error with a parameter
     * @throws ApiUnavailableException if the API is unavailable
     */
    List<BookingContract> getVehiclesMove(GetBranchVehicleMovesContract contract)  throws ApiUnauthorizedException, ApiException, ApiInvalidParameterException, ApiUnavailableException;
} public class CarRentalApiClientFactory {
    /**
     * Creates a new API client with the default IP and port values
     *
     * @return api client
     */
    public static CarRentalApiClient getApiClient() {
        return new CarRentalApiClientSocketImpl(
                PreferencesManager.getHeadOfficeIpAddress(CarRentalApplication.getAppContext()),
                PreferencesManager.getHeadOfficePort(CarRentalApplication.getAppContext()));
    }

    /**
     * Creates a new API client with the given IP and port values
     * @param ipAddress given ip address
     * @param port given port
     * @return api client
     */
    public static CarRentalApiClient getApiClient(String ipAddress, int port) {
        return new CarRentalApiClientSocketImpl(ipAddress, port);
    }
} public class BookingSearchResultContract {
    public boolean requireVehicleMove;
    public VehicleContract vehicle;
    public String pickupDate;
    public String returnDate;
    public long daysCount;
    public double price;
} public class CreateAccountRequestContract {
    public String fullName;
    public String emailAddress;
    public String phoneNumber;
    public String password;
    public String address_street;
    public String address_city;
    public String address_postalCode;
    public String address_country;
} public class CreateUpdateVehicleContract {
    public int type;
    public String registrationNumber;
    public int doors;
    public int seats;
    public boolean automaticTransmission;
    public double poundsPerDay;
    public String name;

    //Update-specific properties
    public boolean isUpdateOperation;
    //public int newBranchId;
    public int id;
    public int newStatusId;
} public class UserContract {
    public int id;
    public boolean isStaff;
    public String fullName;
    public String emailAddress;
    public String phoneNumber;
} public class VehicleContract {
    public int id;
    public BranchContract branch;
    public int type;
    public int status;
    public String registrationNumber;
    public int doors;
    public int seats;
    public boolean automaticTransmission;
    public double poundsPerDay;
    public String name;
} public class ActivityUtils {

    /**
     * This method will display an error message depending on which error has been thrown by the API
     *
     * @param context current context
     * @param apiException expression thrown by the API client
     */
    public static void HandleException(Context context, Exception apiException) {
        Toast toast;
        if (apiException instanceof ApiUnauthorizedException) {
            toast = Toast.makeText(context, R.string.error_invalid_account_credentials, Toast.LENGTH_SHORT);
            PreferencesManager.clearSession(context);
        } else if (apiException instanceof ApiInvalidParameterException) {
            toast = Toast.makeText(context, String.format(context.getString(R.string.ends_with_a_dot), apiException.getMessage()), Toast.LENGTH_SHORT);
        } else if (apiException instanceof ApiUnavailableException) {
            toast = Toast.makeText(context, R.string.error_server_not_available, Toast.LENGTH_SHORT);
        } else {
            toast = Toast.makeText(context, R.string.error_server_not_reachable, Toast.LENGTH_SHORT);
        }
        toast.show();
    }

    /**
     * This method will build the left drawer on the android application in every activity which calls it
     *
     * The drawer is composed of many different items, each of them executing a specific action when clicked
     *
     * @param activity the current activity
     */
    public static void buildDrawer(final AppCompatActivity activity) {
        BranchContract branchContract = PreferencesManager.getCurrentBranch(activity);
        String branchName = branchContract == null ? activity.getString(R.string.no_branch_selected) : branchContract.name;

        /* Login */
        PrimaryDrawerItem loginItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_perm_identity_black_24dp)
            .withName(R.string.login_register_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    PreferencesManager.clearSession(activity);
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), LoginActivity.class);
                    //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    activity.startActivity(intent);
                    return true;
                }
            }
        );

        /* Change connection settings */
        PrimaryDrawerItem changeIpSettings = new PrimaryDrawerItem()
                .withIcon(R.drawable.ic_settings_black_24dp)
                .withName(R.string.change_server_settings_menu_item)
                .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                                   @Override
                                                   public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), ChangeConnectionSettingsActivity.class);
                    intent.putExtra(LoginActivity.COMES_FROM_LOGIN, false);
                    activity.startActivity(intent);
                    return true;
               }
            }
        );

        /* Logout */
        PrimaryDrawerItem logoutItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_perm_identity_black_24dp)
            .withName(R.string.logout_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    PreferencesManager.clearSession(activity);
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), LoginActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    activity.startActivity(intent);
                    return true;
                }
            }
        );

        /* Change Branch */
        PrimaryDrawerItem changeBranchItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_room_black_24dp)
            .withName(String.format(activity.getString(R.string.change_branch_menu_item), branchName))
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), ChooseBranchActivity.class);
                    activity.startActivity(intent);
                    return true;
                }
            }
        );

        /* Search Vehicle */
        PrimaryDrawerItem searchBookingItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_search_black_24dp)
            .withName(R.string.search_available_vehicles_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), SearchAvailableVehicleActivity.class);
                    activity.startActivity(intent);
                    return true;
                }
            }
        );

        /* USER: Show user bookings */
        PrimaryDrawerItem userBookings = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_view_list_black_24dp)
            .withName(R.string.user_bookings_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), UserBookingsActivity.class);
                    activity.startActivity(intent);
                    return true;
                }
            }
        );

        /* ADMIN: Search vehicle */
        PrimaryDrawerItem searchVehicleItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_search_black_24dp)
            .withName(R.string.search_vehcile_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                               @Override
                                               public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                   Intent intent = new Intent(CarRentalApplication.getAppContext(), SearchVehicleActivity.class);
                   activity.startActivity(intent);
                   return true;
                }
            }
        );

        /* ADMIN: DO Client booking vehicle */
        PrimaryDrawerItem bookForClientItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_directions_car_black_24dp)
            .withName(R.string.make_client_booking_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                               @Override
                                               public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                   Intent intent = new Intent(CarRentalApplication.getAppContext(), SearchAvailableVehicleActivity.class);
                   activity.startActivity(intent);
                   return true;
                    }
            }
        );

        /* ADMIN: AddVehicle */
        PrimaryDrawerItem addVehicleItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_add_black_24dp)
            .withName(R.string.add_vehicle_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                                   @Override
                                                   public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                   Intent intent = new Intent(CarRentalApplication.getAppContext(), CreateVehicleActivity.class);
                   activity.startActivity(intent);
                   return true;
                                                   }
            }
        );

        /* ADMIN: Show branch bookings */
        PrimaryDrawerItem showBranchBookingsItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_view_list_black_24dp)
            .withName(R.string.view_branch_bookings_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                               @Override
                                               public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                   Intent intent = new Intent(CarRentalApplication.getAppContext(), BranchBookingsActivity.class);
                   activity.startActivity(intent);
                   return true;
                                               }
            }
        );

        /* ADMIN: Show Moves */
        PrimaryDrawerItem showMovesItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_swap_horiz_black_24dp)
            .withName(R.string.view_branch_moves_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                                   @Override
                                                   public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                   Intent intent = new Intent(CarRentalApplication.getAppContext(), ShowBranchMovesActivity.class);
                   activity.startActivity(intent);
                   return true;
                                                   }
            }
        );

        /* ADMIN: sys admin */
        PrimaryDrawerItem sysAdminItem = new PrimaryDrawerItem()
            .withIcon(R.drawable.ic_power_settings_new_black_24dp)
            .withName(R.string.server_control_menu_item)
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                                                   @Override
                                                   public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    Intent intent = new Intent(CarRentalApplication.getAppContext(), SystemAdministrationActivity.class);
                    activity.startActivity(intent);
                    return true;
                                                   }
            }
        );

        //Instantiate the builder
        DrawerBuilder drawerBuilder = new DrawerBuilder()
                .withActivity(activity)
                .withDisplayBelowStatusBar(false)
                .withTranslucentStatusBar(false)
                .withSelectedItem(-1);

        //Instantiate the header builder
        AccountHeaderBuilder headerBuilder = new AccountHeaderBuilder()
                .withActivity(activity)
                .withHeaderBackground(R.drawable.drawer_header)
                .withSelectionListEnabledForSingleProfile(false);

        //Finalize configuration, depending on user leverl
        if (PreferencesManager.isLoggedIn(activity)) {
            UserContract user = PreferencesManager.getLoggedUser(activity);

            if (PreferencesManager.isStaffUser(activity)) {
                //Staff drawer
                AccountHeader headerResult = headerBuilder
                    .addProfiles(new ProfileDrawerItem()
                        .withName(String.format(activity.getString(R.string.staff_user_label), user.fullName))
                        .withEmail(user.emailAddress)
                        .withIcon(R.drawable.icon))
                    .build();

                drawerBuilder
                    .withAccountHeader(headerResult)
                    .addDrawerItems(logoutItem, changeBranchItem, searchVehicleItem, addVehicleItem, bookForClientItem, showBranchBookingsItem, showMovesItem, sysAdminItem, changeIpSettings);
            } else {
                //User drawer
                AccountHeader headerResult = headerBuilder
                    .addProfiles(new ProfileDrawerItem()
                        .withName(user.fullName)
                        .withEmail(user.emailAddress)
                        .withIcon(R.drawable.icon))
                    .build();

                drawerBuilder
                    .withAccountHeader(headerResult)
                    .addDrawerItems(logoutItem, changeBranchItem, searchBookingItem, userBookings, changeIpSettings);
            }
        } else {
            //User drawer
            AccountHeader headerResult = headerBuilder
                .addProfiles(new ProfileDrawerItem()
                    .withName(activity.getString(R.string.not_logged_in))
                    .withIcon(R.drawable.icon))
                .build();

            drawerBuilder
                .withAccountHeader(headerResult)
                .addDrawerItems(loginItem, changeBranchItem, searchBookingItem, changeIpSettings);
        }

        //Build the drawer
        Drawer drawer = drawerBuilder.build();
    }
} public class SerializationUtils {

    //Static gson object
    private static Gson gsonObject = new Gson();

    /**
     * Serialize the provided object to a json string
     *
     * @param object the object to serialize
     * @param <T> the generic object type
     * @return the serialized json string
     */
    public static <T> String serialize(T object) {
        return gsonObject.toJson(object);
    }

    /**
     * Deserialize the provided string into the given type
     *
     * @param serialized the serialized json string
     * @param type the expected object type
     * @param <T> the generic object type
     * @return the deserialized object
     */
    public static <T> T deserialize(String serialized, Type type) {
        return gsonObject.fromJson(serialized, type);
    }
} public class StaticDataUtils {

    //Data structures to provide an easy access to the static data
    private static ArrayList<String> vehicleTypes;
    private static ArrayList<String> vehicleStatuses;
    private static Map<String, BranchContract> branchContractMap;

    /**
     * Registers all the available vehicle types in memory
     */
    private static void initializeVehicleTypes() {
        vehicleTypes = new ArrayList<>();
        vehicleTypes.add(0, CarRentalApplication.getAppContext().getString(R.string.small_car_type));
        vehicleTypes.add(1, CarRentalApplication.getAppContext().getString(R.string.family_car_type));
        vehicleTypes.add(2, CarRentalApplication.getAppContext().getString(R.string.small_van_type));
        vehicleTypes.add(3, CarRentalApplication.getAppContext().getString(R.string.large_van_type));
    }

    /**
     * Registers all the available vehicle status in memory
     */
    private static void initializeVehicleStatuses() {
        vehicleStatuses = new ArrayList<>();
        vehicleStatuses.add(0, CarRentalApplication.getAppContext().getString(R.string.available_status));
        vehicleStatuses.add(1, CarRentalApplication.getAppContext().getString(R.string.in_transit_status));
        vehicleStatuses.add(2, CarRentalApplication.getAppContext().getString(R.string.in_client_booking_status));
        vehicleStatuses.add(3, CarRentalApplication.getAppContext().getString(R.string.maintenance_status));
    }

    /**
     * Registers the branches in memory
     * We are using a hashmap, because the branches will be mapped through their name
     *
     * @param branches the branch list
     */
    public static void setBranches(List<BranchContract> branches) {
        branchContractMap = new HashMap<>();
        for (BranchContract branch : branches) {
            branchContractMap.put(branch.name, branch);
        }
    }

    /**
     * Returns the list of vehicle types, and initialize it if it has not been done yet
     *
     * @return the vehicle types list
     */
    public static ArrayList<String> getVehicleTypesList() {
        if (vehicleTypes == null) {
            initializeVehicleTypes();
        }

        return vehicleTypes;
    }

    /**
     * Returns the list of vehicle types as an array, and initialize it if it has not been done yet
     *
     * @return the vehicle types array
     */
    public static String[] getVehicleTypesArray() {
        return getVehicleTypesList().toArray(new String[getVehicleTypesList().size()]);
    }

    /**
     * Returns the list of vehicle statuses, and initialize it if it has not been done yet
     *
     * @return the vehicle statuses list
     */
    public static ArrayList<String> getVehicleStatusesList() {
        if (vehicleStatuses == null) {
            initializeVehicleStatuses();
        }

        return vehicleStatuses;
    }

    /**
     * Returns the list of vehicle statuses as an array, and initialize it if it has not been done yet
     *
     * @return the vehicle statuses array
     */
    public static String[] getVehicleStatusesArray() {
        return getVehicleStatusesList().toArray(new String[getVehicleStatusesList().size()]);
    }

    /**
     * Returns the array of the branch names
     *
     * @return the branch names arrays
     */
    public static String[] getBranchNamesArray() {
        return branchContractMap.keySet().toArray(new String[branchContractMap.size()]);
    }

    /**
     * Return the branch matching the given name
     *
     * @param name given branch name
     * @return the branch if it exists, null otherwise
     */
    public static BranchContract getBranchFromName(String name) {
        return branchContractMap.get(name);
    }
}
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.vehiclerental.R;
import com.vehiclerental.activities.Guest.BookingSearchResultsActivity;
import com.vehiclerental.activities.User.BookVehicleActivity;
import com.vehiclerental.apiClient.CarRentalApiClient;
import com.vehiclerental.apiClient.CarRentalApiClientFactory;
import com.vehiclerental.contracts.BookingSearchResultContract;
import com.vehiclerental.contracts.CreateAccountRequestContract;
import com.vehiclerental.contracts.CreateUpdateVehicleContract;
import com.vehiclerental.contracts.UserContract;
import com.vehiclerental.contracts.VehicleContract;
import com.vehiclerental.utils.ActivityUtils;
import com.vehiclerental.utils.SerializationUtils;
import com.vehiclerental.utils.StaticDataUtils;
import java.security.InvalidParameterException;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
 * CarRental
 *
 * This activity displays a form to create a new vehicle in the current branch
 */

package com.vehiclerental.activities.Staff;





public class CreateVehicleActivity extends AppCompatActivity {

    //Automatic binding with Butterknife (external library)
    @Bind(R.id.vehicleName)
    protected EditText vehicleName;
    @Bind(R.id.vehicleRegistrationNumber)
    protected EditText vehicleRegistrationNumber;
    @Bind(R.id.numberOfDoors)
    protected EditText numberOfDoors;
    @Bind(R.id.numberOfSeats)
    protected EditText numberOfSeats;
    @Bind(R.id.automaticTransmission)
    protected CheckBox automaticTransmission;
    @Bind(R.id.vehicleTypePicker)
    protected Spinner vehicleTypePicker;
    @Bind(R.id.pricePerDay)
    protected EditText pricePerDay;
    @Bind(R.id.createVehicleButton)
    protected Button createVehicleButton;

    //private members
    private CreateUpdateVehicleContract createUpdateVehicleContract;
    private CarRentalApiClient apiClient = CarRentalApiClientFactory.getApiClient();

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

        ButterKnife.bind(this);
        ActivityUtils.buildDrawer(this);

        setTitle(getString(R.string.create_vehicle_title));

        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, StaticDataUtils.getVehicleTypesArray());