:- module(episode_data, [retract_episode/1,
			 lookup_episode/3,
			 lookup_episode_local/3,
			 lookup_episode_remote/3]).

:- use_module(library(dcg/basics)).
:- use_module(library(http/http_open)).
:- use_module(library(sgml)).
:- use_module(library(xpath)).
:- use_module(library(persistency)).
:- use_module(atom_dcg).

:- persistent episode_name_data(episode:integer, name:atom, data:list).

attach :-
	absolute_file_name('episode_data.db', F, [access(write)]),
	db_attach(F, []).

detach :-
	db_detach.

retract_episode(Ep) :-
	(   episode_name_data(Ep, _, _)
	->  retractall_episode_name_data(Ep, _, _)
	;   true
	).

padding(Ep) --> { Ep < 10 }, "00".
padding(Ep) --> { Ep >= 10, Ep < 100 }, "0".
padding(Ep) --> { Ep >= 100 }.

episode_number(Ep) --> padding(Ep), integer(Ep).

lookup_episode(Ep, Name, Data) :- lookup_episode_local(Ep, Name, Data), !.
lookup_episode(Ep, Name, Data) :- lookup_episode_remote(Ep, Name, Data).

lookup_episode_local(Ep, Name, Data) :-
        episode_name_data(Ep, Name, Data).

lookup_episode_remote(Ep, Name, Data) :-
	catch(http_load_html(
		  'https://www.detectiveconanworld.com/wiki/Next_Conan%27s_Hint',
		  D),
	      _,
	      fail),
	xpath(D, //tr, D1),
	xpath(D1, td(index(1),text), T),
	atom_phrase(episode_number(Ep), T),
	xpath(D1, td(index(2),text), Name),
	xpath(D1, td(index(3),text), Hint),
	Data = [hint(Hint)],
        assert_episode_name_data(Ep, Name, Data).

http_load_html(URL, DOM) :-
        setup_call_cleanup(http_open(URL, In,
                           [ timeout(60)
                           ]),
                           (   dtd(html, DTD),
                               load_structure(stream(In),
                                              DOM,
                                              [ dtd(DTD),
                                                dialect(sgml),
                                                shorttag(false),
                                                max_errors(-1),
                                                syntax_errors(quiet)
                                              ])
                           ),
                           close(In)).