def update_db_start_date_min_end_date_max(path_db):
    if path_db is not None:
        dbquery = query_database.DbQuery(path_db)
        minDate, maxDate = dbquery.get_date_range()
        return minDate.strftime('%Y-%m-%d'), maxDate.strftime('%Y-%m-%d')
    else:
        return None, None
def update_camera_ids(path_db):
    if path_db is not None:
        #print(path_db)
        dbquery = query_database.DbQuery(path_db)
        return dbquery.get_cam_id_options()
    else:
        return []
def is_database_valid(path_db):
    try:
        dbTemp = query_database.DbQuery(path_db)
        tableName = 'vectorkb_table'
        if tableName in dbTemp.get_table_list():
            return True#'cam_id' in dbTemp.get_columns_list(tableName)
        else:
            return False
    except:
        return False
def show_results_images(pathname, search):#, n_clicks, start_date, start_hour, start_minute, end_date, end_hour, end_minute, cam_id, threshold):
    # dict_trig = get_callback_trigger()

    # if 'url' in dict_trig or 'results-filter-button' not in dict_trig:
    #     start_date = None
    #     end_date = None
    #     cam_id = None
    #     threshold = None

    # params = extract_results_search_params(pathname, search)
    # if params is not None:
    #     if 'database' in params:
    #         path_db = params['database']
    #     else:
    #         path_db = None
    #     if 'image_id' in params:
    #         img_id = params['image_id']
    #     else:
    #         img_id = None
    #     if 'image' in params:
    #         img = params['image']
    #     else:
    #         img = None
    #     if 'image_filename' in params:
    #         img_name = params['image_filename']
    #     else:
    #         img_name = None
    # else:
    #     return

    path_db, img_id, img, img_filename, start_datetime, end_datetime, cam_id, threshold = decode_results_search_params(pathname, search)

    if threshold is None:
        threshold = 0.6

    row_images = []
    if path_db is not None and (img_id is not None or img is not None) and os.path.exists(path_db):
        dbquery = query_database.DbQuery(path_db)
        if img_id is not None:
            df = dbquery.get_images(img_id=img_id)
            row = df.iloc[0]
            image = row.img
        else:
            image = img

        result = run_reid(image, path_db, threshold)

        dict_result = {}
        for item in result:
            for key in item:
                if key in dict_result:
                    dict_result[key].append(item[key])
                else:
                    dict_result[key] = [item[key]]

        if len(dict_result) > 0:
            df = pd.DataFrame.from_dict(dict_result)
            list_cams = sorted(df.cam_id.unique().tolist())
            if cam_id is not None:
                if cam_id in list_cams:
                    list_cams = [cam_id]
                else:
                    list_cams = None

            # start_datetime = compile_start_datetime(start_date, start_hour, start_minute)
            # end_datetime = compile_end_datetime(end_date, end_hour, end_minute)
            if list_cams is not None and len(list_cams) > 0:
                for cam_id in list_cams:
                    cam_images=[]
                    header = f'Camera {cam_id}'
                    for _, row_cam in df[df.cam_id == cam_id].iterrows():
                        db_reid = query_reid.DbQuery(path_db)
                        df_query = db_reid.get_images(row_cam.img_id)
                        df_query.timestamp = pd.to_datetime(df_query.timestamp)
                        if start_datetime is not None:
                            df_query = df_query[df_query.timestamp >= start_datetime]
                        if end_datetime is not None:
                            df_query = df_query[df_query.timestamp < end_datetime]
                        if len(df_query) > 0:
                            if "loc" in df_query.columns:
                                header = f'Camera {cam_id} {df_query[df_query.cam_id == cam_id]["loc"].iloc[0]}'
                            for idx_query, row_query in df_query.iterrows():
                                encoded_image = base64.b64encode(row_query.img)
                                id_tag = f'result-img-id-{row_query.img_id}'
                                tooltip = []
                                if row_query.img_id is not None:
                                    tooltip.extend([
                                        html.B('Image ID:'),
                                        html.Br(),
                                        html.Span(row_query.img_id),
                                        html.Br(),
                                    ])
                                if row_query.timestamp is not None:
                                    tooltip.extend([
                                        html.B('Date time detected:'),
                                        html.Br(),
                                        html.Span(row_query.timestamp),
                                        html.Br(),
                                    ])
                                if row_cam.dist is not None:
                                    tooltip.extend([
                                        html.B('Similarity: '),
                                        #html.Br(),
                                        html.Span(round(row_cam.dist,4)),
                                    ])
                                cam_images.append(
                                    dbc.Card(
                                        id=id_tag,
                                        children=[
                                            dbc.CardImg(
                                                src='data:image/png;base64,{}'.format(encoded_image.decode()),
                                                #id=id_tag,
                                                #title=tooltip_msg.strip(),
                                                style={
                                                    'width': '8vw',
                                                    'object-fit': 'contain',
                                                    #'margin':'5%',
                                                },
                                            ),
                                            dbc.Tooltip([
                                                html.P(tooltip, style={'text-align': 'left'}),
                                                dbc.Button(
                                                    html.B('Query this'),
                                                    id=f'query-img-id-{row_query.img_id}',
                                                    size="md",
                                                    href=get_results_href(path_db, img_id=row_query.img_id),
                                                    ),
                                                ],
                                                target=id_tag,
                                                autohide=False,
                                                style={'font-size': 'small'},
                                            )
                                        ]
                                    ))

                    if len(cam_images) > 0:
                        row_images.append(
                            dbc.Card([
                                dbc.CardHeader(header, style={'font-weight': 'bold'}),
                                dbc.CardBody(dbc.Row(cam_images),style={'margin': '1%'},),
                            ]))

    if len(row_images) <= 0:
        row_images.append(html.P('No results found!'))

    return row_images
def show_database_images(path_db, start_date, start_hour, start_minute, end_date, end_hour, end_minute, cam_id, upload_img, upload_filename):
    dict_trig = get_callback_trigger()
    if 'upload-image' in dict_trig:
        images_col = []
        for img, filename in zip(upload_img, upload_filename):
            tooltip_msg = f"File name: {filename}"
            images_col.append(
                dbc.Card([
                    dbc.CardLink(
                        dbc.CardImg(
                            src=img,
                            title=tooltip_msg.strip(),
                            style={
                                'width': '8vw',
                                'object-fit': 'contain'
                            },
                        ),
                        key=filename,
                        # f'{urlResults}?{urlencode(url_dict)}'
                        href=get_results_href(
                            path_db, img=img, img_filename=filename)
                    ),
                ])
            )
        return images_col
    elif path_db is not None and cam_id is not None:
        dbimage = query_database.DbQuery(path_db)
        start_datetime = compile_start_datetime(start_date, start_hour, start_minute)
        end_datetime = compile_end_datetime(end_date, end_hour, end_minute)
        df_images = dbimage.get_images(
            cam_id=cam_id, start_datetime=start_datetime, end_datetime=end_datetime)
        images_col = []
        for _, row in df_images.iterrows():
            encoded_image = base64.b64encode(row.img)
            components = [
                #html.P(f'Camera {row.cam_id}', style={'text-overflow': 'ellipsis', 'width': '8vw', 'margin': '0'})
            ]

            timestamp = row.timestamp
            if timestamp is not None:
                if type(timestamp) == str:
                    timestamp = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')
                components.extend([
                    html.P(timestamp.date(),
                                         style={'text-overflow': 'ellipsis', 'width': '8vw', 'margin': '0'}),
                    html.P(timestamp.strftime("%X"),
                           style={'text-overflow': 'ellipsis', 'width': '8vw', 'margin': '0'}),
                    ])

            components.append(
                html.Img(
                    src='data:image/png;base64,{}'.format(encoded_image.decode()),
                    title=row.img_id,
                    style={
                        'width': '8vw',
                        'object-fit': 'contain'
                    }
                ))

            tooltip_msg = ""
            if (row.img_id is not None):
                tooltip_msg += f"Image ID: {row.img_id}\r\n"
            if (timestamp is not None):
                tooltip_msg += f"Datetime: {timestamp}\r\n"
            if (row.cam_id is not None):
                tooltip_msg += f"Camera ID: {row.cam_id}\r\n"
            if "loc" in df_images.columns:
                tooltip_msg += f'Location: {row["loc"]}\r\n'
            images_col.append(
                dbc.Card([
                    dbc.CardLink(
                        dbc.CardImg(
                            src='data:image/png;base64,{}'.format(encoded_image.decode()),
                            title=tooltip_msg.strip(),
                            style={
                                'width': '8vw',
                                'object-fit': 'contain'
                            },
                        ),
                        key=row.img_id,
                        href=get_results_href(path_db, img_id=row.img_id)#f'{urlResults}?{urlencode(url_dict)}'
                    ),
                ])
            )
        return images_col
    else:
        return None
def results_page_content(params):
    if 'database' in params:
        path_db = params['database']
    else:
        path_db = None
    if 'image_id' in params:
        img_id = params['image_id']
    else:
        img_id = None
    if 'image' in params:
        img = params['image']
    else:
        img = None
    if 'image_filename' in params:
        img_name = params['image_filename']
    else:
        img_name = None

    sidebar_contents = []

    # Show selected image
    if path_db is not None and os.path.exists(path_db):
        dbquery = query_database.DbQuery(path_db)
        minDate, maxDate = dbquery.get_date_range()
        details_row = []
        image=None
        if img_id is not None:
            df = dbquery.get_images(img_id=img_id)
            row = df.iloc[0]
            encoded_image = base64.b64encode(row.img)
            image = 'data:image/png;base64,{}'.format(encoded_image.decode())
            if row.img_id is not None:
                details_row.append(dbc.Row(
                    [
                        html.B('Image ID:', style={'margin-right': '5px'}),
                        html.P(row.img_id),
                    ],
                    #className="card-text",
                ))
            if row.timestamp is not None:
                details_row.append(dbc.Row(
                    [
                        html.B('Date/Time:', style={'margin-right': '5px'}),
                        html.P(row.timestamp),
                    ],
                    #className="card-text",
                ))
            if row.cam_id is not None:
                details_row.append(dbc.Row(
                    [
                        html.B('Camera ID:', style={'margin-right': '5px'}),
                        html.P(row.cam_id),
                    ],
                    #className="card-text",
                ))
            if "loc" in df.columns and row["loc"] is not None:
                details_row.append(dbc.Row(
                    [
                        html.B('Location:', style={'margin-right': '5px'}),
                        html.P(row["loc"]),
                    ],
                    #className="card-text",
                ))
        elif img is not None:
            image = img
            if img_name is not None:
                details_row.append(dbc.Row(
                    [
                        html.B('File Name:', style={'margin-right': '5px'}),
                        html.P(img_name),
                    ],
                ))
        if image is not None:
            sidebar_contents.append(
                dbc.Card(
                    children=[
                        dbc.CardImg(
                            id='results-sidebar-image',
                            src=image,
                            style={
                                'width': '8vw',
                                'object-fit': 'contain',
                            },
                        ),
                        dbc.CardBody(details_row),
                    ],
                    style={
                        'padding': '5%',
                    },
                )
            )

    # filter
    sidebar_contents.append(
        dbc.Card([
            dbc.CardBody([
                html.H6('Search Filter', style={
                    'font-weight': 'bold', 'color': '#007fcf',}),
                #html.Br(),
                dbc.Col([
                        html.P('Select Start Date & Time', style={'font-weight': 'bold'}),
                        dbc.Col([
                            dbc.Row([
                                dbc.Col(html.P('Date:'), width='auto', align='center'),
                                dbc.Col(
                                    dcc.DatePickerSingle(
                                        id='results-filter-date-start-id',
                                        display_format='DD-MM-YYYY',
                                        min_date_allowed=minDate.strftime('%Y-%m-%d'),
                                        max_date_allowed=maxDate.strftime('%Y-%m-%d')),
                                    width=True),
                            ]),
                            dbc.Row([
                                dbc.Col(html.P('Hour (0 ~ 23):'), width='auto', align='center'),
                                dbc.Col(dbc.Input(id='results-filter-time-start-hr-id', type='number', min=0, max=23), width=True),
                            ]),
                            dbc.Row([
                                dbc.Col(html.P('Minute (0 ~ 59):'), width='auto', align='center'),
                                dbc.Col(dbc.Input(id='results-filter-time-start-min-id', type='number', min=0, max=59), width=True),
                            ]),
                        ]),
                        #dash_datetimepicker.DashDatetimepicker(id='results-filter-datetime'),
                        ], style={'padding': '1%'}),
                dbc.Col([
                        html.P('Select End Date & Time', style={'font-weight': 'bold'}),
                        dbc.Col([
                            dbc.Row([
                                dbc.Col(html.P('Date:'), width='auto', align='center'),
                                dbc.Col(
                                    dcc.DatePickerSingle(
                                        id='results-filter-date-end-id',
                                        display_format='DD-MM-YYYY',
                                        min_date_allowed=minDate.strftime('%Y-%m-%d'),
                                        max_date_allowed=maxDate.strftime('%Y-%m-%d')),
                                    width=True),
                            ]),
                            dbc.Row([
                                dbc.Col(html.P('Hour (0 ~ 23):'), width='auto', align='center'),
                                dbc.Col(dbc.Input(id='results-filter-time-end-hr-id', type='number', min=0, max=23), width=True),
                            ]),
                            dbc.Row([
                                dbc.Col(html.P('Minute (0 ~ 59):'), width='auto', align='center'),
                                dbc.Col(dbc.Input(id='results-filter-time-end-min-id', type='number', min=0, max=59), width=True),
                            ]),
                        ]),
                        #dash_datetimepicker.DashDatetimepicker(id='results-filter-datetime'),
                        ], style={'padding': '1%'}),
                dbc.Col([
                        html.P('Camera ID', style={'font-weight': 'bold'}),
                        dcc.Dropdown(id='results-filter-cam-id',
                                   options=dbquery.get_cam_id_options()),
                        ], style={'padding': '1%'}),
                dbc.Col([
                        html.P(children='Threshold (Default is 0.60)',
                            style={'font-weight': 'bold'}),
                        dbc.Input(id='results-filter-threshold',type='number', step=0.01, value=0.6),
                    ],
                    style={'padding': '1%'}),
                html.Br(),
                dbc.Button(children="Filter", id='results-filter-button', color="primary",
                           block=True, size='lg'),
            ]),
        ])
    )

    return dbc.Row(children=[
        dbc.Col(
            id='results-page-sidebar',
            children=sidebar_contents,
            width=3,
            style=SIDEBAR_STYLE,
        ),
        dbc.Col(dbc.Spinner(
            id='display-results-col',
            #width=True,
        ),width=True,),
    ])
def is_database_valid(path_db):
    try:
        dbTemp = query_database.DbQuery(path_db)
        return 'vectorkb_table' in dbTemp.get_table_list()
    except:
        return False
def show_database_images(path_db, start_date, end_date, cam_id):
    if path_db is not None and \
        start_date is not None and \
            end_date is not None and \
                cam_id is not None:
        #print(path_db)
        #print(start_date, end_date)
        #print(cam_id)
        dbimage = query_database.DbQuery(path_db)
        df_images = dbimage.get_images(
            cam_id=cam_id, start_datetime=None, end_datetime=None)
        #print(df_images.info())
        images_col = []
        images_col1 = []
        urlResults = '/results'
        for _, row in df_images.iterrows():
            encoded_image = base64.b64encode(row.img)
            components = [
                #html.P(f'Camera {row.cam_id}', style={'text-overflow': 'ellipsis', 'width': '8vw', 'margin': '0'})
            ]
            #url_dict = {'database': os.path.basename(path_db), 'image_id': row.img_id}
            url_dict = {'database': path_db, 'image_id': row.img_id}

            if row.timestamp is not None:
                components.extend([
                    html.P(row.timestamp.date(),
                                         style={'text-overflow': 'ellipsis', 'width': '8vw', 'margin': '0'}),
                    html.P(row.timestamp.strftime("%X"),
                           style={'text-overflow': 'ellipsis', 'width': '8vw', 'margin': '0'}),
                    ])

            components.append(
                html.Img(
                    src='data:image/png;base64,{}'.format(encoded_image.decode()),
                    title=row.img_id,
                    #id=img_id,
                    style={
                        'width': '8vw',
                        'object-fit': 'contain'
                    }
                ))

            images_col1.append(
                dbc.Col(
                    children=[
                        dbc.Spinner(html.A(
                            id={'index': row.img_id, 'type': 'image'},
                            key=row.img_id,
                            children=components,
                            href=f'{urlResults}?{urlencode(url_dict)}'
                        ))
                    ],
                    width='auto',
                    align='start',
                ))
            tooltip_msg = ""
            if (row.img_id is not None):
                tooltip_msg += f"Image ID: {row.img_id}\r\n"
            if (row.timestamp is not None):
                tooltip_msg = f"Datetime: {row.timestamp}\r\n"
            if (row.cam_id is not None):
                tooltip_msg += f"Camera ID: {row.cam_id}\r\n"
            images_col.append(
                dbc.Card([
                    dbc.CardLink(
                        dbc.CardImg(
                            src='data:image/png;base64,{}'.format(encoded_image.decode()),
                            title=tooltip_msg.strip(),
                            style={
                                'width': '8vw',
                                'object-fit': 'contain'
                            },
                        ),
                        key=row.img_id,
                        href=f'{urlResults}?{urlencode(url_dict)}'
                    ),
                ])
            )
        return images_col
    else:
        return None
def results_page_content(path_db=None, img_id=None):
    sidebar_contents = []

    # Show selected image
    if path_db is not None and img_id is not None and os.path.exists(path_db):
        dbquery = query_database.DbQuery(path_db)
        df = dbquery.get_images(img_id=img_id)
        row = df.iloc[0]
        print(row)
        encoded_image = base64.b64encode(row.img)
        details_row = []
        if row.img_id is not None:
            details_row.append(dbc.Row(
                [
                    html.B('Image ID:', style={'margin-right':'5px'}),
                    html.P(row.img_id),
                ],
                #className="card-text",
            ))
        if row.timestamp is not None:
            details_row.append(dbc.Row(
                [
                    html.B('Date/Time:', style={'margin-right': '5px'}),
                    html.P(row.timestamp),
                ],
                #className="card-text",
            ))
        if row.cam_id is not None:
            details_row.append(dbc.Row(
                [
                    html.B('Camera ID:', style={'margin-right':'5px'}),
                    html.P(row.cam_id),
                ],
                #className="card-text",
            ))
        sidebar_contents.append(
            dbc.Card(
                children=[
                    dbc.CardImg(
                        id='results-sidebar-image',
                        src='data:image/png;base64,{}'.format(
                            encoded_image.decode()),
                        style={
                            'width': '8vw',
                            'object-fit': 'contain',
                        },
                    ),
                    dbc.CardBody(details_row),
                ],
                style={
                    'padding': '5%',
                },
            )
        )

    # filter
    sidebar_contents.append(
        dbc.Card([
            dbc.CardBody([
                html.H6('Search Filter', style={
                    'font-weight': 'bold', 'color': '#007fcf',}),
                html.Br(),
                dbc.Col([
                        html.P('Select Date & Time', style={
                               'font-weight': 'bold'}),
                        dash_datetimepicker.DashDatetimepicker(
                            id='results-filter-datetime'),
                        ], style={'padding': '1%'}),
                dbc.Col([
                        html.P('Camera ID', style={'font-weight': 'bold'}),
                        dbc.Input(id='results-filter-cam-id',type='number', step=1),
                        ], style={'padding': '1%'}),
                dbc.Col([
                        html.P(children='Threshold (Default is 0.6)',
                            style={'font-weight': 'bold'}),
                        dbc.Input(id='results-filter-threshold',type='number', step=0.1, value=0.6),
                    ],
                    style={'padding': '1%'}),
                html.Br(),
                dbc.Button(children="Filter", id='results-filter-button', color="primary",
                           block=True, size='lg'),
            ]),
        ])
    )

    return dbc.Row(children=[
        dbc.Col(
            id='results-page-sidebar',
            children=sidebar_contents,
            width=3,
            style=SIDEBAR_STYLE,
        ),
        dbc.Col(
            id='display-results-col',
            width=True,
        ),
    ])