const
	script_name='allmovie';
	language='English';
	version=15;
	author='Vlad';
	MinProgramBuild=5500;
	PCount = 12;
	//MaxPicturesCount = 3;
var
	DownloadMovieBigCover, DownloadMovieShortCast, DownloadMovieFullCast, 
	DownloadMovieBigDescription, DownloadMovieComments, 
	DownloadMovieStudios,	DownloadMovieAwards, DownloadMovieEarnings, 
	DownloadMovieAdditionalInfo, DownloadMovieSeasonsList: boolean;
	MaxShotsCount, MaxPostersCount: integer;

	title, MovieName, s, s2, s3, s4, year, director, name, character, BasicURL, country, description, salary, awards: string;
	episodes, movie_code, movie_site_url, title_code, imdb_code: string;
	titles: array of string;
	titles_count: integer;
	i, j: integer;
	director_code, code: string;
	directors, writers, actors, characters, genres, imdb_codes: array of string;
	duration: integer;
	rating, imdb_rating: double;
	front_cover_url: string;
	posters_exists, ask_amazon: boolean;
	original_title, mpaa, mpaa_rating: string;
	prefixes: array [1..PCount] of string;
	resolution, barcode, aspect_ratio, features, media_format, video_codec: string;

function GetStr(str: String; s1: String; s2: String): String;
var
  I: Integer;
  J: Integer;
begin
  // Вырезает кусок строки между s1 и s2
	Result := '';
	I := Pos(s1, str);
	if I > 0 then
	begin
		J := MyPos(s2, str, I + Length(s1));
		if J > 0 then
  		Result := Copy(str, I + Length(s1), J - I - Length(s1));
	end;
end;

function ClearExtraBlankCharacters(text: string): string;
begin
	// Clear all extra blank charackters
	while (length(text) > 0) and (ord(text[1]) in [1..32]) do
		delete(text, 1, 1);
	while (length(text) > 0) and (ord(text[length(text)]) in [1..32]) do
		delete(text, length(text), 1);
	Result := text;
end;
	
function DeleteBadChars(text: String): String;
var
	i: Integer;
	s : String;
begin
	s := '';
	for i := 1 to Length(text) do begin
		if not (ord(text[i]) in [1..20]) then
			s := s + text[i];
	end;
	Result := s;
end;

function MovieSearch: integer;
var
	i, j, k, l: integer;
	title, tempCode, small_cover, year, director, description: string;
begin
	s:='';
	titles_count:=0;
	//if the search is forwarded to the movie's page (only one result)
	if (pos('<ul class="results">', all)<=0) then begin
		title_code:=ParseString(all, 'sql=1:(\d+)~T0">', 1);
		if title_code<>'' then begin
			//we don't care about titles here
			SetSearchResult('movie', title_code);
			titles_count:=1;
		end;
	end
	//otherwise check seach results
	else begin		
		i:=pos('<ul class="results">', all);
		if i>0 then begin
			j:=MyPos('</ul>', all, i+1);
			if j>0 then
				s:=copy(all, i, j-i);
		end;
		if (s='') or (pos('<h1>Oops! No results', all)>0) then
			//Movie not found
		else begin
			i := pos('<li',s);
			while i>0 do begin
				tempCode := GetStr(s, '<li', '</li>');
				small_cover := GetStr(tempCode, '<img src="', '?partner');
				title_code:=ParseString(tempCode, '<a href="http://www.allmovie.com/movie/.*?-v(\d+)"', 1);
				title := GetStr(tempCode, '<a href="http://www.allmovie.com/movie/', '/a>');
				title := GetStr(title, '>', '<');
				title:=RemoveTags(title);
				title:=DecodeHTML(title);
				title:=ClearExtraBlankCharacters(title);
				year := ParseString(tempCode, '<a href="http://www.allmovie.com/movie/.*?\((\d+)\)', 1);
				director := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(tempCode, '<dd class="director">', '</dd>'))));
				description := ClearExtraBlankCharacters(DecodeHTML(RemoveTags(GetStr(tempCode, '<dd class="genre">', '</dd>'))));
				if (title <> '') and (title_code <> '') then begin
					SetSearchResult2(title, title_code, year, director, description, small_cover);
					titles_count:=titles_count+1;
				end;
				delete(s, 1, i);
				i := pos('<li',s);
			end;
		end;
	end;
	result:=titles_count;
end;

//get  movie name by barcode(UPC-12)
function GetMovieNameByUPC(barcode: string): string;
var
	url, all, s2, s3, res: string;
	i, j: integer;
begin
	res:='';
	url:=format('http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&SubscriptionId=0J0N83PT9M72BYH98YR2&Operation=ItemSearch&Keywords=%s&SearchIndex=Video&ResponseGroup=Request,Images,Tracks,ItemAttributes', [barcode]);	
	url:=ReplaceStr(url, ' ', '+', -1);
	all:=DownloadURL(url);
	//search image by title
	i:=pos('<Item>', all);
	while (i>0) and (res='') do begin
		j:=MyPos('</Item>', all, i+1);
		if j>0 then begin
			s2:=copy(all, i, j-i);
			s3:=ParseString(s2, '<Title>(.*?) \(.*\)</Title>', 1);
			if s3='' then
				s3:=ParseString(s2, '<Title>(.*?)</Title>', 1);
			if s3<>'' then
				res:=s3;
		end;
		i:=MyPos('<Item>', all, i+1);
	end;
	i:=pos('[', res);
	if i>0 then begin
		j:=MyPos(']', res, i+1);
		if j>0 then
			delete(res, i, j-i+1);
	end;
	result:=res;
end;

//Get search URL by movie name
function GetSearchURLbyName(MovieName, AYear, ABarcode: string): string;
var
	url: string;
begin
	url:=format('http://www.allmovie.com/search/movies/%s', [MovieName]);
	url:=ReplaceStr(url, ' ', '+', -1);
	result:=url;
end;

//Download search results from URL
function DownloadSearchURL(url: string): integer;
begin
	all:=DownloadURL(url);
	if all='-1' then
		result:=-1
	else
		result:=MovieSearch;
end;

function GetMovieURL(code: string; images_only: boolean): string;
begin
	if Pos('dvd', code)>0 then begin
		delete(code, 1, 3);
		result := format('http://www.allmovie.com/dvd/%s', [code]);
	end
	else
		result:=format('http://www.allmovie.com/movie/v%s', [code]);
end;

//returned link to front cover
function GetAmazonImages: string;
var
	res, all, url, s, s2, s3, amazon_url, my_title: string;
	i, j: integer;
begin
	//discard info in brackets
	s:=title;
	my_title := title;
	i := Pos('[', my_title);
	if i>0 then
		delete(my_title, i, length(my_title) - i + 1);
	url:=format('http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&SubscriptionId=0J0N83PT9M72BYH98YR2&Operation=ItemSearch&Keywords=%s&SearchIndex=Video&ResponseGroup=Request,Images,Tracks,ItemAttributes', [my_title]);
	url:=ReplaceStr(url, ' ', '+', -1);
	all:=DownloadURL(url);
	//search image by title
	amazon_url:='';
	i:=pos('<Item>', all);
	while (i>0) and (amazon_url='') do begin
		j:=MyPos('</Item>', all, i+1);
		if j>0 then begin
			s2:=copy(all, i, j-i);
			s3:=ParseString(s2, '<Title>(.*?) \(.*\)</Title>', 1);
			if s3='' then
				s3:=ParseString(s2, '<Title>(.*?)</Title>', 1);
			s3:=DecodeHTML(s3);
			if s3<>'' then 
			begin
				//if title=s3 then begin //!!!
				if pos(UpperCase(title), UpperCase(s3))=1 then 
				begin
					amazon_url:=ParseString(s2, '<LargeImage><URL>(.*?)</URL>', 1);
				end;
			end;
		end;
		i:=MyPos('<Item>', all, i+1);
	end;
	if amazon_url<>'' then begin
		SetImageName('', amazon_url, '', 1);
		res:=amazon_url;
	end;
	result:=res;
end;

//save front cover to file
function SaveFrontCover(url, FileName: string): boolean;
var
  fs: TFileStream;
	s: string;
begin
	s:=DownloadURL(url);
	if (length(s)>0) and (s<>'-1') then begin
		try
			fs:=TFileStream.Create(FileName, fmCreate);
			fs.Write(s, Length(s));
			fs.Free;
			result:=true;
		except
			result:=false;
		end;
	end
	else
		result:=false;
end;

function MovePrefixLeft(name: string): string;
var
	i, j: integer;
begin
	// replace "The", "A", "An"... to the left
	for j:=1 to PCount do
	begin
		i:=pos(', '+Prefixes[j], name);
		if i>0 then
			if (i = length(name)-length(Prefixes[j])-1) or
			(length(name) >= i+2+length(Prefixes[j])) and (name[i+2+length(Prefixes[j])]=':') then
			begin
				if Prefixes[j][length(Prefixes[j])] = '''' then
					name := Prefixes[j] + copy(name, 1, i-1) + copy(name, i+length(Prefixes[j])+2, length(name)-i-length(Prefixes[j])-2+1)
				else
					name := Prefixes[j]+' ' + copy(name, 1, i-1) + copy(name, i+length(Prefixes[j])+2, length(name)-i-length(Prefixes[j])-2+1);
				break;
			end;
	end;
	Result := name;
end;

function ClearExtraQuotes(name: string): string;
begin
	// Clears extra quotes «"»
	if length(name)>0 then
		if (name[1]='"') and (name[length(name)]='"') then
			name := copy(name,2,length(name)-2);
	Result := name;
end;

function ExtractAwards(text: string): string;
var
	i, j, k, l, m, n: integer;
	s, s2, my_award, nominations, aw_title, win_nom : string;
	won, nom, very_first: boolean;
begin
	my_award:='';
	nominations:='';
	very_first := true;
	i:=Pos('<h3 class="award">', text);
	//process lines in the table sequentally
	while i>0 do begin
		j:=MyPos('</table>', text, i+1);
		if j = 0 then
			j := Length(text);
		nominations:='';
		won := False;
		nom := False;
		s := copy(text, i, j-i);
		s := DeleteBadChars(s);
		k := Pos('</h3>', s);
		aw_title := copy(s, 1, k-1);
		aw_title := RemoveTags(aw_title);
		aw_title := DecodeHTML(aw_title);
		aw_title := ClearExtraSpaces(aw_title);
		if not very_first then
			my_award := my_award + '<br><br>';
		very_first := false;
		my_award := my_award + aw_title;
		delete(s, 1, k+4);
		k := Pos('<td class="award-title">', s);
		while k > 0 do begin
			l := MyPos('</td>', s, k+1);
			s2 := copy(s, k, l-k);
			if Pos('<div class="recipients">&nbsp;</div>', s2) = 0 then
				s2 := ReplaceStr(s2, '<div class="recipients">', ': ', -1);
			s2 := RemoveTags(s2);
			s2 := DecodeHTML(s2);
			s2 := ClearExtraSpaces(s2);
			while (Pos('  ', s2)>0) do
				delete(s2, Pos('  ', s2), 1);
			win_nom := LowerCase(ClearExtraBlankCharacters(RemoveTags(GetStr(s, '<td class="award-type">', '</td>'))));
			if win_nom = 'won' then begin
				if not won then
					my_award := my_award + '<br>Won';
				won := true;
				my_award := my_award + '<br>' + s2;
			end
			else begin
				if not nom then
					nominations := '<br>Nominated';
				nom := true;
				nominations := nominations + '<br>' + s2;
			end;
			delete(s, 1, l);
			k := Pos('<td class="award-title">', s);
			break;
		end;
		my_award:=my_award+nominations;
		delete(text, 1, j-1);
		i:=Pos('<h3 class="award">', text);
	end;
	Result:=my_award;
	
end;


function GetInfo(url: string; images_only: boolean): string;
var 
	keyword, s, s2, s3, plot_outline, shot, shot_prefix, shot_ext, my_url, temp, small_photo: string;
	i, j, k, l, frames_count: integer;
	actors, awards_exist: boolean;
begin
	result:='';
	all := DownloadURL(url);
	if all='-1' then
		result:='-1'
	else
		result:=all;
		
	s := GetStr(all, '<div class="page-title">', '</div>');
	title := GetStr(s, 'itemprop="name">', '<');
	title := ClearExtraBlankCharacters(DecodeHTML(title));
	year := ParseString(s, '\((\d+)\)', 1);
	
	if (DownloadMovieAwards) and (pos('/awards', all)>0) then
		AddRequestForHTMLPageContent(url + '/awards', False);
		
	if (DownloadMovieFullCast) and (Pos('/cast-crew', all)>0) then
		AddRequestForHTMLPageContent(url + '/cast-crew', False);
	
	movie_code := ParseString(url, '(\d+)$', 1);
	movie_site_url:=GetMovieSiteURL(movie_code);

	if title='' then
		exit;
		
	//original title - not found
	
	//mpaa
	s := GetStr(all, 'class="mpaa_rating ', '"');
	s := UpperCase(s);
	if s = 'PG13' then
		s := 'PG-13';
	if s = 'NC17' then
		s := 'NC-17';
	mpaa := s;
	
	//mpaa reasons
	s := GetStr(all, '<dt>flags</dt>', '</dd>');
	mpaa_rating := '';
	while (Pos('<li>', s)>0) do begin
		if mpaa_rating <> '' then
			mpaa_rating := mpaa_rating + ', ';
		mpaa_rating := mpaa_rating + LowerCase(ClearExtraBlankCharacters(RemoveTags(GetStr(s, '<li>', '</li>'))));
		delete(s, 1, Pos('<li>', s));
	end;
	
	//genres
	s := GetStr(all, '<dt>genres</dt>', '</dd>');
	while (Pos('<li>', s)>0) do begin
		SetGenre(ClearExtraBlankCharacters(RemoveTags(GetStr(s, '<li>', '</li>'))));
		delete(s, 1, Pos('<li>', s));
	end;
	
	//directors
	s := GetStr(all, '<dt>directed by</dt>', '</dd>');
	while (Pos('<li>', s)>0) do begin
		s2 := GetStr(s, '<li>', '</li>');
		name := ClearExtraBlankCharacters(RemoveTags(s2));
		code := ParseString(s2, ' href="http://www.allmovie.com/artist/.*?(\d+)"', 1);
		if (name <> '') and (code <> '') then
			SetPersonName(name, '', 1, code);
		delete(s, 1, Pos('<li>', s));
	end;
	
	//countries
	s := GetStr(all, '<dt>countries</dt>', '</dd>');
	s := ClearExtraBlankCharacters(RemoveTags(s));
	while (s <> '') do begin
		i := Pos(',', s);
		if i=0 then
			i := Length(s)+1;
		SetCountry(copy(s, 1, i-1));
		delete(s, 1, i+1);
	end;
	
	//editor rating
	s := GetStr(all, 'editor rating</dt>', '</dd>');
	s := GetStr(s, 'itemprop="rating">', '</span');
	i := Pos('.', s);
	if i > 0 then
		s[i] := DecimalSeparator;
	try
		rating := StrtoFloat(s);
	except
	end;
	
	//duration
	s := GetStr(all, '<dt>run time</dt>', '</dd>');
	s3 := ParseString(s, '(\d+)', 1);
	try
		duration:=StrToInt(s3);
	except
	end;
	
	//Studios
	if DownloadMovieStudios then begin
		s := GetStr(all, '<dt>produced by</dt>', '</dd>');
		s := ClearExtraBlankCharacters(RemoveTags(s));
		while (s <> '') do begin
			i := Pos(',', s);
			if i=0 then
				i := Length(s)+1;
			SetStudio(copy(s, 1, i-1));
			delete(s, 1, i+1);
		end;
		s := GetStr(all, '<dt>released by</dt>', '</dd>');
		s := ClearExtraBlankCharacters(RemoveTags(s));
		while (s <> '') do begin
			i := Pos(',', s);
			if i=0 then
				i := Length(s)+1;
			SetStudio(copy(s, 1, i-1));
			delete(s, 1, i+1);
		end;
	end;
	
	//synopsis
	description := ClearExtraBlankCharacters(RemoveTags(GetStr(all, '<strong>synopsis</strong>', '<div class="toggle fade">')));
	description := ReplaceStr(description, #10, #13#10, -1);
	
	//cover art
	s := GetStr(all, '<meta property="og:image" content="', '?partner');
	if (RegReadInteger('AllMovieFullSizeCovers', 0) = 1) then begin
		i := Pos('/_derived', s);
		if i>0 then begin
			j := MyPos('/', s, i+1);
			delete(s, i, j-i);
		end;
	end
	else
		s := ReplaceStr(s, '116x177', '410x410', -1);
	if (s <> '') and (Pos('no_cover', s)=0) then
		front_cover_url := s;
		
	//Cast and crew
	if DownloadMovieFullCast then begin
		temp := GetHTMLPageContentFromRequest(url + '/cast-crew');
		//cast
		i := Pos('<h2>cast</h2>', temp);
		if i>0 then begin
			j := MyPos('<h2>', temp, i+1);
			s := copy(temp, i, j-i);
			while (Pos('<div class="cast_container">', s)>0) do begin
				s2 := GetStr(s, '<div class="cast_container">', '</dl>');
				small_photo := GetStr(s2, '<img src="', '?partner');
				if (RegReadInteger('AllMovieFullSizePhotos', 0) = 1) then begin
					i := Pos('/_derived', small_photo);
					if i>0 then begin
						j := MyPos('/', small_photo, i+1);
						delete(small_photo, i, j-i);
					end;
				end
				else
					small_photo := ReplaceStr(small_photo, '80x60', '410x410', -1);
				code := ParseString(s2, 'href="http://www.allmovie.com/artist/.*?p(\d+)"', 1);
				name := ClearExtraBlankCharacters(RemoveTags(GetStr(s2, '<dt class="name">', '</dt>')));
				character := ClearExtraBlankCharacters(RemoveTags(GetStr(s2, '<dd>', '</dd>')));
				if name<>'' then
					SetPersonName(name, character, 3, code, small_photo);
				delete(s, 1, Pos('<div class="cast_container">', s));
			end;
		end;
		//crew
		i := Pos('<h2>crew</h2>', temp);
		if i>0 then begin
			j := MyPos('</dl>', temp, i+1);
			s := copy(temp, i, j-i);
			while (Pos('<dt>', s)>0) do begin
				s2 := GetStr(s, '<dt>', '</div>');
				if (Pos('Screenwriter', s2)>0) or (Pos('Composer', s2)>0) then begin
					name := ParseString(s2, '<a href.*?">(.*?)</a>', 1);
					name := ClearExtraBlankCharacters(RemoveTags(name));
					code := ParseString(s2, 'href="http://www.allmovie.com/artist/.*?p(\d+)', 1);
					if (Pos('Screenwriter', s2)>0) then
						SetPersonName(name, '', 2, code);
					if (Pos('Composer', s2)>0) then
						SetPersonName(name, '', 4, code);
				end;
				delete(s, 1, Pos('<dt>', s));
			end;
		end;
	end;
	
	//Awards
	if DownloadMovieAwards then begin
		temp := GetHTMLPageContentFromRequest(url + '/awards');
		s := GetStr(temp, '<div class="awards-box">', '<div id="footer">');
		awards := ExtractAwards(s);
	end;
	
end;

procedure GetShots;
var
	s, shot_url: String;
	shots_cnt, i, j: Integer;
begin
	shots_cnt := 0;
	s := GetStr(all, '<div class="movie-stills">', '<div class="tab-title">');
	while (shots_cnt < MaxShotsCount) and (Pos('<img src="', s)>0) do begin
		shot_url := GetStr(s, '<img src="', '?partner');
		if (RegReadInteger('AllMovieFullSizeShots', 0) = 1) then begin
			i := Pos('/_derived', shot_url);
			if i>0 then begin
				j := MyPos('/', shot_url, i+1);
				delete(shot_url, i, j-i);
			end;
		end;
		if shot_url <> '' then begin
			shots_cnt := shots_cnt + 1;
			SetImageName('', shot_url, '', 3);
		end;
		delete(s, 1, Pos('<img src="', s));
	end;
end;

//returned images links
procedure GetImages;
begin
	if front_cover_url<>'' then
		SetImageName('', front_cover_url, '', 1);
		//GetAmazonImages;
	GetShots;
end;

//get movie site url
function GetMovieSiteURL(code: string): string;
begin
	if code='' then
		result:=''
	else
		result:='http://www.allmovie.com/movie/v'+code;
end;

//get person site url
function GetPersonSiteURL(code: string): string;
begin
	if code='' then
		result:=''
	else
		result:='http://www.allmovie.com/artist/p'+code;
end;

//show available settings for the script
function ShowScriptOptions: integer;
var
	s: string;
	f: TForm;
	b: TButton;
	cbFullSizeCovers, cbFullSizeShots: TCheckBox;
	my_value: integer;

procedure ButtonClick(Sender: TButton);
var
	zn: integer;
begin
	try
		if cbFullSizeCovers.Checked then
			zn := 1
		else
			zn := 0;
		RegWriteInteger('AllMovieFullSizeCovers', zn);
		if cbFullSizeShots.Checked then
			zn := 1
		else
			zn := 0;
		RegWriteInteger('AllMovieFullSizeShots', zn);		
	except
	end;

	f.ModalResult := mrOk;
end;

begin
	result:=0;
	f := TForm.Create(nil);
	f.Caption := GetLangStr(1924);
	f.BorderStyle := bsDialog;
	f.Position := poScreenCenter;
	f.Width:=400;
	f.Height:=210;
	f.AutoSize:=false;

	
	cbFullSizeCovers := TCheckBox.Create(f);
	cbFullSizeCovers.Name := 'cbFullSizeCovers';
	cbFullSizeCovers.Parent := f;
	cbFullSizeCovers.SetBounds(10, 10, 350, 20);
	cbFullSizeCovers.Caption := 'Download full-size (huge) covers';
	my_value := RegReadInteger('AllMovieFullSizeCovers', 0);
	if my_value=1 then
		cbFullSizeCovers.Checked := True;
		
	cbFullSizeShots := TCheckBox.Create(f);
	cbFullSizeShots.Name := 'cbFullSizeShots';
	cbFullSizeShots.Parent := f;
	cbFullSizeShots.SetBounds(10, 30, 350, 20);
	cbFullSizeShots.Caption := 'Download full-size shots';
	my_value := RegReadInteger('AllMovieFullSizeShots', 0);
	if my_value=1 then
		cbFullSizeShots.Checked := True;
		

	b := TButton.Create(f);
	b.Name := 'btnOK';
	b.Parent := f;
	b.SetBounds(160, 150, 80, 25);
	b.Caption := '&OK';
	b.OnClick := @ButtonClick;

	f.ShowModal;
	f.Free;
end;


begin

prefixes[1]:='The';
prefixes[2]:='A';
prefixes[3]:='An';
prefixes[4]:='La';
prefixes[5]:='Les';
prefixes[6]:='Des';
prefixes[7]:='L''';
prefixes[8]:='Un';
prefixes[9]:='El';
prefixes[10]:='Il';
prefixes[11]:='Le';
prefixes[12]:='Uno';

end.