#!/usr/bin/perl -W
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
#
# Copyright (c) 2019 Amlogic, Inc. All rights reserved.
#
my $top = ".";
my $err_cnt = 0;
my $k_v = 4;
my $exit = 0;
my $git_format_link="http://wiki-china.amlogic.com/Platform/Bootloader/Bootloader_commit_message_format";
my $config1 = "arch/arm64/configs/meson64_a64_smarthome_defconfig";
my $skip = 0;
my $make_build_link = "https://confluence.amlogic.com/display/SW/5.+c2+bringup";
my $make_defconfig_link = "https://confluence.amlogic.com/display/SW/1.+Quick+Start";
my $env_common = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
my $arm64_dts = "arch/arm64/boot/dts/amlogic/";
my $arm_dts = "arch/arm/boot/dts/amlogic/";

#Check mesonxx_defconfig
sub check_defconfig
{
	my $arm64_config = `git diff  --name-only arch/arm64/configs | grep  -E *defconfig`;
	my $is_common_drivers = `pwd | grep -E *common_drivers*`;
	if (!$arm64_config || !$is_common_drivers)
	{
		return 0;
	}
	my $err = 0;
	#print "2. Check meson_defconfig: ";
	if( -e $config1)
	{
		`cd .. && mkdir -p out/kernel-5.15/common`;
		`cd .. && export CROSS_COMPILE=/opt/gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-`;
		`cd .. && cp -rf common_drivers/arch/arm64/configs/meson64_a64_smarthome_defconfig  common/arch/arm64/configs/`;
		`cd .. && make ARCH=arm64 -C ${PWD}/common/ O=${PWD}/out/kernel-5.15/common/ meson64_a64_smarthome_defconfig`;
		`cd .. && make ARCH=arm64 -C ${PWD}/common/ O=${PWD}/out/kernel-5.15/common/ savedefconfig`;
		`cd .. && rm -rf  ../common/arch/arm64/configs/meson64_a64_smarthome_defconfig`;
		`cd .. && rm -rf ../out/kernel-5.15/common/.config`;
		my $diff =  `diff ../out/kernel-5.15/common/defconfig arch/arm64/configs/meson64_a64_smarthome_defconfig`;
		if(length($diff))
		{
			$err_cnt += 1;
			$err = 1;
			$err_msg .= "    $err_cnt: meson64_a64_smarthome_defconfig not generated by savedefconfig\n";
		}
	}


	if($err)
	{
		$err_msg .= "    Please refer to:\n";
		$err_msg .= "            $make_defconfig_link \n";
		$err_msg .= "            $make_build_link\n";
	}
	#print $err ? "fail\n" : "success\n";
}

sub dts_check
{
	my $is_common_drivers = `pwd | grep -E *common_drivers*`;
	if (!$is_common_drivers)
	{
		return 0;
	}
	my @dts_path = @_;
	my $dts_diff = "";
	my $diff = `git diff  --name-only @dts_path | grep -E *dts\$`;
	if (!$diff)
	{
		return 0;
	}
	my $all_dts = `find @dts_path -name "*dts"`;
	my @diff_str = split /[\n]/, $diff;
	my @all_dts_str = split /[\n]/, $all_dts;
	my $diff_count = 0;
	my $all_dts_count = 0;
	my $count = 0;
	my $t = 0;
	my $q = 0;
	my $temp = "";
	my @arry = ("");
	my @arry1 = ("");
	my @arry2 = ("");
	for (@diff_str)
	{
		$re = $_;
		if ($re=~m/^(.*?)\_/)
		{
			$dts_diff = $1;
			$dts_diff =~ /@dts_path/;
			$temp=$';
			$dts_diff = $dts_diff."_";
		}
		if (!($_ =~ "pxp.dts"))
		{
			for (@diff_str)
			{
				if ($_ =~ $dts_diff)
				{
					$_ =~ /@dts_path/;
					$arry1->[$diff_count] = $';
					$diff_count = $diff_count+1;
				}
			}
			for (@all_dts_str)
			{
				if (!($_ =~ "pxp.dts"))
				{
					if ($_ =~ $dts_diff)
					{
						$all_dts_count=$all_dts_count+1;
						$_ =~ /@dts_path/;
						$arry->[$all_dts_count] = $';
					}
				}
			}
		}
		if ($diff_count != $all_dts_count)
		{
			$count=$count+1;
		}
		while ($q<$t)
		{
			if ($arry2->[$q] =~ $temp )
			{
				$count=0;
			}
			$q=$q+1;
		}
		if ($count != 0)
		{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt:You are modifying  the board $temp DTS file in @dts_path \n";
		$err_msg .= "	  You have modified dts is ";
		while($diff_count > 0)
		{
			$err_msg .= "$arry1->[$diff_count-1] ";
			$diff_count=$diff_count-1;
		}
		$err_msg .= "\n";
		$err_msg .= "	  Please confirm should you modify other boards for $temp in @dts_path too? ";

		$err_msg .= "\n";
		$count = 0;
		$diff_count = 0;
		$all_dts_count = 0;
		$arry2->[$t]=$temp;
		$t=$t+1;
		$q=0;
		}
	}
}

sub check_dtsi
{
	my $file = `git diff  --name-only  | grep -E *dtsi\$`;
	my $arm_dts_num = () = ($file =~ /arch\/arm\/boot\/dts\/amlogic/g);
	my $arm64_dts_num = () = ($file =~ /arch\/arm64\/boot\/dts\/amlogic/g);

	if( $arm_dts_num != $arm64_dts_num )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: maybe should modify dtsi in both arm and arm64\n";
	}
}

# check module_param number
sub check_module_param
{
	my $num = `git format-patch -1 --stdout | grep -c "module_param("`;
	my $MAX_NUM = 5;

	if( $num > $MAX_NUM )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: the number of module_param too much\n";
	}
}

my $MAX_LEN	=	100;

sub check_msg_common
{
	my $line = pop(@_);
	my $lnum = pop(@_);

	if( (length($line) > ($MAX_LEN + 4) ) && ($lnum > 4) )
	{	#Line over 100 characters is not allowed.
		$line =~ s/^(\s){4}//;
		$err_cnt += 1;
		$err_msg .= "    $err_cnt: Line over $MAX_LEN characters: <$line>\n";
	}

	if ( ($line =~ /\s+$/) && $line !~/^(\s){4}$/ )
	{ #No space at the end of line
		$err_cnt += 1;
		$line =~ s/^(\s){4}//;
		$err_msg .= "    $err_cnt: No space at the end of line: <$line>\n";
	}
}


sub check_msg_49_2
{
	my $msg = `git cat-file commit HEAD~0 | sed '1,/\^\$/d'`;
	my @str = split /[\n][\n]/, $msg;
	my $i = 0;
	my $len = @str;

	if( $msg =~ /^Revert\s/ )
	{
		return 0;
	}

	if( $len != 6 )
	{
		$err_cnt += 5;
		$err_msg .= "	module: message [n/m]\n\n";
		$err_msg .= "	PD#SWPL-XXXX\n\n";
		$err_msg .= "	Problem:\n	detailed description\n\n";
		$err_msg .= "	Solution:\n	detailed description\n\n";
		$err_msg .= "	Verify:\n	detailed description\n\n";
		return -1;
	}

	if( $msg !~ /Merge\s/ && $msg =~ /5\.15/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: this branch is 5.15, all changes here are for 5.15. No「5.15」in commit message please\n";
	}

	if( $str[$i] !~ /^([\w-]+:\s){1,2}.+(\s)\[[\d]+\/[\d]+\]$/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: module: message [n/m]\n";
	}
	elsif( $str[$i] =~ /(kernel)/i )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: Should be no 'kernel' in kernel commit message\n";
	}

	if( $str[++ $i] !~ /^PD\#SWPL-.+(\d)$/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: PD#SWPL-XXXX\n";
		return -1;

	}

	if( $str[++ $i] !~ /^Problem:[\n].+/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: Problem:\n	detailed description\n";
		return -1;
	}

	$i += 1;
	while( $str[$i] !~ /^Solution:[\n].+/ && $str[$i] !~ /^Change-Id:/ && $str[$i] !~ /^Verify:[\n].+/ && ($i + 1) < $len )
	{
		$i = $i + 1;
	}

	if( $str[$i] !~ /^Solution:[\n].+/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: Solution:\n	detailed description\n";
		return -1;
	}

	if( $str[$i] =~ /^Change-Id:/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: Verify:\n	detailed description\n";
		return -1;
	}

	while( $str[$i] !~ /^Verify:[\n].+/ && $str[$i] !~ /^Change-Id:/ && ($i + 1) < $len )
	{
		$i += 1;
	}

	if( $str[$i] !~ /^Verify:[\n].+/ )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: Verify:\n	detailed description\n";
	}
}

sub sync_arm64_arm_diff
{
	my $file = `git diff --name-only HEAD HEAD^`;
	my $arm_dts_num = () = ($file =~ /arch\/arm\/boot\/dts\/amlogic/g);
	my $arm64_dts_num = () = ($file =~ /arch\/arm64\/boot\/dts\/amlogic/g);
	my $arm_config_num = () = ($file =~ /arch\/arm\/config/g);
	my $arm64_config_num = () = ($file =~ /arch\/arm64\/config/g);

	if( $arm_config_num != $arm64_config_num )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: maybe should modify the config in both arm and arm64\n";
	}
	if( $arm_dts_num != $arm64_dts_num )
	{
		$err_cnt += 1;
		$err_msg .= "	$err_cnt: maybe should modify the dts in both arm and arm64\n";
	}
}

sub check_nonascii_character
{
	my $add_msg = `git format-patch -1 --stdout | sed -e '/^-/d'`;
	my @add_str =  split /[\n][\n]/,, $add_msg;
	my $i = 0;
	my $len = @add_str;
	for ($i = 0; $i < $len; $i = $i + 1)
	{
		if (!$add_str[$i] =~ m/[^\x00-\x7f]/)
		{
			$err_cnt += 1;
			$err_msg  .= "	@add_str[$i]\n";
		}
	}
}


sub check_commit_msg
{

	my $lnum = 0;
	my $err = 0;
	my $result = 0;
	my $commit;
	my $FILE;

	open($FILE, '<&STDIN');

	while (<$FILE>) {
		chomp;
		my $line = $_;


		if( $line =~ /^commit\s([0-9a-z])+$/)
		{
			$lnum = 0;
			$commit = $line;
			$skip = 0;
		}
		$lnum ++;


		if( ($lnum ==2) && ($line =~ /^Merge: /))
		{
			#$skip =1;			#Don't Check branch merge
		}
		if( ($lnum==2) && ($line !~ /^Author: .*\@amlogic\.com\>$/))
		{
			#$skip =1;			#Don't Check commit which is not from amlogic
		}

		if( $err == 1)
		{
			$skip = 1;
			$err = 0;
			$result = 1;
		}
		if( $skip ==1)
		{
			next;
		}

		check_msg_common($lnum, $line);
	}
	close $FILE;
	if ($k_v >= 4)
	{
		check_msg_49_2;
	}
}

sub out_review
{
	my $out_msg = "";
	my $out_file = "../output/review.txt";

	if ($err_cnt)
	{
		$out_msg = <<END;
		\$ total $err_cnt errors.
${err_msg}

END

		#open O, "> $out_file" or die "Can't Open $out_file For Write \n";
		#print O $out_msg;
		#close O;
		$exit = 1;
		print $out_msg;
		print "Please refer to:\n	$git_format_link\n";
	}
	else
	{
		print "";
	}
}

#start

my $err_msg_p = "\nCommit Pre check failed. Total $err_cnt errors.\n";

#Check meson_defconfig
check_defconfig();
dts_check($arm64_dts);
#dts_check($arm_dts);
#check_dtsi();

#check_module_param
check_module_param();

#Check commit message
#check_commit_msg();

#check config and dts in arm and arm64
#sync_arm64_arm_diff();
check_nonascii_character();

out_review();
#out
exit $exit;
