def __initialize_DB(self):
        """

            Create and initialize a new DB, including the downloading and \
            uploading of two lists from Open Food Facts: the stores and the\
            categories.

            Arguments:

            NIL

            Returns:

            NIL

            """
        self.queries = sql.ORMConnection()
        self.queries.create_database()
        self.itf.right_display_info(cfg.DB_CREATE_LOCAL_DB)
        self.queries = sql.ORMConnection()
        # Open the connection to the local DB
        self.queries.open_session()
        # Import categories from Open Food Facts
        OFF_categories = self.OFF.import_static_data(coff.URL_STATIC_CAT)
        # Configure the data and upload categories into the local DB
        self.queries.upload_categories(OFF_categories)
        self.itf.right_display_info(cfg.DB_CATEGORIES_FETCHED)
        # Import stores from Open Food Facts
        OFF_stores = self.OFF.import_static_data(coff.URL_STATIC_STORES)
        # Configure the data and upload stores into the local DB
        self.queries.upload_stores(OFF_stores)
        self.itf.right_display_info(cfg.DB_STORES_FETCHED)
        # Informs the user that the DB is empty.
        self.itf.right_display_info(cfg.EMPTY_DB, "warning")
    def __create_cnx_parameters(self):
        """
            This method is activated if no DB has been created. \
            All the parameters are asked and the script for the creation is run

            Arguments:

            NIL

            Returns:

            NIL
            """
        self.itf.clear_window("left")
        self.itf.display_guide(cfg.USER_GUIDE)
        y = 0
        while True:
            # Ask for the connection parameters. Default value in config.py
            password, y = self.itf.display_string_textpad(y, 1, 20,
                                                        cfg.DB_PASSWORD_INVITE)
            password = self.__ascii_to_string(password)
            if password != '':
                cfg.DB_PASSWORD = password
            connection_string = cfg.DB_CONNEXION_STRING.format(
                cfg.DB_USER, cfg.DB_PASSWORD, "")
            with open(cfg.DB_PARAMETERS, "w") as file:
                file.write(connection_string)
            try:
                # Test parameters before recording.
                self.queries = sql.ORMConnection()
                break
            except Exception:
                self.itf.right_display_info(cfg.WARNING_MSG_5, "warning")
                y = 0
    def step_select_action(self):
        """

            Represent the main menu to navigate in the application.
            This is where the connection with the class MySQLQueries is instantiated.

            Arguments:

            self.queries: instanciate the class sql.ORMConnection iot manage the
            relation with the model.

            Returns:

            decision: used to give the main function the order to quit the app.

            """
        # Check whether a local DB has already been created.
        while True:
            try:
                # Check whether a connection with an existing local DB is OK.
                self.queries = sql.ORMConnection()
                break
            except Exception:
                # Creation of a connexion, iot prepare the DB creation
                self.itf.clear_window("right")
                self.itf.right_display_info(cfg.WARNING_MESSAGE_4, "warning")
                self.__create_cnx_parameters()
                # Creation of the DB through a method hosted in this module
                self.__initialize_DB()
        self.itf.title_bar(cfg.TITLE_2)
        # Display a drop down menu to navigate in the application
        self.itf.clear_window()
        self.itf.left_display_string(0, cfg.INFO_LINE_1)
        self.itf.display_result(cfg.INFO_DISPLAY_RESULTS)
        answer = self.itf.set_up_drop_down(cfg.OPERATE_ON_DB,
                                           cfg.SELECT_ANSWER)
        # Here start the work on the DB to find, select and record a product
        y = 0
        while True:
            # Open a session with the ORM iot work with the DB.
            self.queries.open_session()
            result = self.queries.total_items()
            # check that the DB is not empty
            if result == 0:
                self.itf.right_display_info(cfg.EMPTY_DB, "warning")
                answer = cfg.OPERATE_ON_DB[2]
            # Look for a product !!
            if answer == cfg.OPERATE_ON_DB[0]:
                self.itf.title_bar(cfg.TITLE_3)
                self.itf.clear_window()
                # list of recorded categories is displayed on the right window.
                top_categories = self.queries.get_categories()
                rank_categories_dict = \
                    self.__display_top_categories(top_categories)
                self.itf.display_guide(cfg.USER_GUIDE)
                # Avoid that a too narrow request leads to an empty selection.
                while True:
                    y = 0
                    self.itf.left_display_string(y, cfg.KEYPAD_INSTRUCTION_1)
                    y += 1
                    answer_category, y = self.__check_valid_answer(y, 1, 3,
                            cfg.SELECT_CATEGORY, rank_categories_dict)
                    # Input the parameters to search for a food item.
                    answer_name, y = self.itf.display_string_textpad(
                        y, 1, 25, cfg.ITEM_NAME)
                    # Launch the query in the local DB.
                    brand_name, y = self.itf.display_string_textpad(
                        y, 1, 25, cfg.ITEM_BRAND)
                    item_search = [answer_category, answer_name, brand_name]
                    refer_products = self.queries.refer_products(item_search)
                    # If the criterion are too specific, avoid a null outcome.
                    if len(refer_products) > 0:
                        break
                    else:
                        self.itf.right_display_info(cfg.WARNING_MESSAGE_2,
                                                    "warning")
                # Display a selection of products.
                rank_item_dict = dict()
                rank_counter = 0
                self.itf.clear_window("right")
                self.itf.display_result(cfg.ITEM_SEARCH_OUTCOME)
                for product in refer_products:
                    rank_counter += 1
                    self.itf.display_result(
                        cfg.PRODUCT_RANK_NAME.format(rank_counter,
                                                     product.name))
                    self.itf.display_result(
                        cfg.PRODUCT_BRAND_NUTR_GR.
                        format(product.brand, product.nutrition_grade))
                    self.itf.display_result(cfg.EMPTY_LINE)
                    # Create key_value of rank and product for further check
                    rank_item_dict[rank_counter] = product.code
                # Requests the user to select a food item to be compared with.
                while True:
                    code_ref_prod, y = self.__check_valid_answer(y, 1, 3,
                                        cfg.COMPARE_FOOD_ITEMS, rank_item_dict)
                    # New keywords are demanded if to restrictive.
                    while True:
                        # The user to enter keywords iot broaden the search
                        keywords_item, y = self.itf.display_string_textpad(
                            y, 1, 25, cfg.ADD_KEYWORDS)
                        # Create tuple with features of reference product
                        selected_prod = answer_category, keywords_item, \
                            code_ref_prod
                        selected_prod = tuple(selected_prod)
                        list_top_products = self.queries.top_products(
                            selected_prod)
                        # Make sure that user's choice isn't too restrictive
                        if len(list_top_products) > 0:
                            break
                        else:
                            self.itf.right_display_info(
                                cfg.WARNING_MESSAGE_1, "warning")
                            y -= 4
                    break
                self.itf.clear_window()
                self.itf.display_guide(cfg.USER_GUIDE)
                # Display the products matching the best user's request.
                top_products_dict = self.__display_top_products(
                    list_top_products)
                while True:
                    y = 0
                    # The user can view the item in a browser and to record it.
                    self.itf.left_display_string(
                        y, cfg.CHECK_DETAILED_RESULT)
                    answer, y = self.itf.display_string_textpad(
                        y+1, 1, 2, cfg.SELECT_Y_N)
                    answer = self.__ascii_to_string(answer).upper()
                    if answer == "Y":
                        code_best_prod, y = self.__check_valid_answer(y, 1, 3,
                                            cfg.USE_BROWSER, top_products_dict)
                        self.OFF.open_product_file_OFF(code_best_prod)
                        self.itf.right_display_info(
                            cfg.RECORD_SELECTED_ITEM)
                        date_time = self.__record_current_DTG()
                        compared_prods = code_best_prod, date_time, \
                            code_ref_prod
                        # Record automatically both selected and ref. products.
                        self.queries.record_comparred_products(compared_prods)
                        self.itf.right_display_info(cfg.PROCESSING_RECORD)
                        break
                    elif answer == "N":
                        break
                    else:
                        answer = self.itf.left_error_input()
                        y -= 4
                # Used to quit this loop an return to the main menu
                self.itf.clear_window()
                answer = self.itf.set_up_drop_down(
                    cfg.OPERATE_ON_DB, cfg.SELECT_ANSWER)

            # Step where the user looks into the best products he has recorded.
            elif answer == cfg.OPERATE_ON_DB[1]:
                self.itf.clear_window()
                last_compared_products = self.queries.get_compared_products()
                # Display the last compared product, reference and best.
                best_products_dict = self.__display_compared_products(
                    last_compared_products)
                # The user can see a product in detail.
                if len(best_products_dict) > 0:
                    self.itf.display_guide(cfg.USER_GUIDE)
                    # User to confirm he wants to see the item in the browser.
                    no_further_check = False
                    while True:
                        y = 0
                        answer, y = self.itf.display_string_textpad(
                                y, 1, 2, cfg.CHECK_AGAIN_ITEMS_Y_N)
                        answer = self.__ascii_to_string(answer).upper()
                        if answer == "Y":
                            # Display the product in the default browser
                            code_product, y =\
                                self.__check_valid_answer(y, 1,
                                                          3, cfg.USE_BROWSER,
                                                          best_products_dict)
                            self.OFF.open_product_file_OFF(code_product)
                        elif answer == "N":
                            no_further_check = True
                            break
                        else:
                            answer = self.itf.left_error_input()
                            y -= 4
                else:
                    # Inform the user that he has no best product yet
                    self.itf.right_display_info(
                        cfg.WARNING_MESSAGE_3, "warning")
                    no_further_check = True
                # Return to the main menu, end of this loop.
                if no_further_check:
                    self.itf.clear_window()
                    answer = self.itf.set_up_drop_down(
                        cfg.OPERATE_ON_DB, cfg.SELECT_ANSWER)

            # Import products from one of the most popular categories.
            elif answer == cfg.OPERATE_ON_DB[2]:
                y = 0
                self.itf.clear_window()
                # Import a short sample of OFF categories and displayed it.
                categories = self.queries.display_categories()
                categories_dict = dict()
                rank_counter = 0
                for category in categories:
                    rank_counter += 1
                    self.itf.display_result(
                        cfg.CAT_RANK_NAME.format(rank_counter, category.name))
                    categories_dict[rank_counter] = category.name

                self.itf.display_guide(cfg.USER_GUIDE)
                # The user is requested to designate a category to be uploaded.
                y = 0
                selected_category, y = \
                    self.__check_valid_answer(y, 1, 3, cfg.ADD_CATEGORY,
                                              categories_dict)
                display_chosen_category = cfg.NAME_IMPORTED_CATEGORY + \
                    selected_category
                self.itf.right_display_info(display_chosen_category)
                # This methods fetches a range of data from Open Food Facts.
                nb_imported, left_apart, list_items = \
                    self.OFF.import_products_list(selected_category)
                # Pieces of info from the downloaded data are given for info.
                self.itf.right_display_info(
                    coff.NUMBER_REJECTED_ITEMS.format(left_apart))
                self.itf.right_display_info(
                    coff.NUMBER_DOWNLOADED_ITEMS.format(nb_imported))
                self.itf.right_display_info(cfg.BE_PATIENT)
                # This is where the excerpt of OFF is uploaded in the local DB.
                self.queries.upload_products(list_items)
                nb_rows = self.queries.total_items()
                self.itf.right_display_info(
                    cfg.ROWS_LOCAL_DB.format(nb_rows))
                # Used to quit this step
                self.itf.clear_window()
                answer = self.itf.set_up_drop_down(
                    cfg.OPERATE_ON_DB, cfg.SELECT_ANSWER)

            # Close properly the program and reinitialize the shell.
            elif answer == cfg.OPERATE_ON_DB[3]:
                self.itf.clear_window()
                self.queries.close_session()
                self.decision = "Quit"
                break
        return self.decision