component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, characters []*arn.Character, friends []*arn.User, topGenres []string, dayToActivityCount map[int]int, uri string)
	.profile
		ProfileHeader(viewUser, user, uri)

		.profile-columns
			//- Favorites
			.profile-column.profile-favorites.mountable(data-mountable-type="column")
				//- Anime
				.profile-section
					h3.profile-column-header.mountable(data-mountable-type="favorites") Anime
					
					if len(animeList.Items) == 0
						p.no-data.mountable(data-mountable-type="favorites") Nothing here yet.
					else
						.profile-favorite-anime-container.mountable(data-mountable-type="favorites")
							each item in animeList.Top(6)
								a.profile-favorite-anime.tip.mountable(href=item.Anime().Link(), aria-label=item.Anime().Title.ByUser(user), data-mountable-type="anime")
									img.profile-favorite-anime-image.lazy(data-src=item.Anime().ImageLink("small"), data-webp=true, alt=item.Anime().Title.ByUser(user))
				
				//- Characters
				.profile-section
					h3.profile-column-header.mountable(data-mountable-type="favorites") Characters
					
					if len(characters) == 0
						p.no-data.mountable(data-mountable-type="favorites") Nothing here yet.
					else
						.profile-favorite-characters-container.mountable(data-mountable-type="favorites")
							each character in characters
								.mountable(data-mountable-type="character")
									CharacterSmall(character, user)
								//- a.profile-favorite-character.tip.mountable(href=character.Link(), aria-label=character.Name.ByUser(user), data-mountable-type="favorite-anime")
								//- 	img.profile-favorite-character-image.lazy(data-src=character.ImageLink("small"), data-webp=true, alt=character.Name.ByUser(user))

			//- Posts
			.profile-column.profile-activity.mountable(data-mountable-type="column")
				.profile-section
					h3.profile-column-header.mountable(data-mountable-type="activity") Posts
					Comments(viewUser, user)
			
			//- Extra
			.profile-column.profile-extra.mountable(data-mountable-type="column")
				//- Genres
				.profile-section
					h3.profile-column-header.mountable(data-mountable-type="extra") Genres

					if len(topGenres) == 0
						p.no-data.mountable(data-mountable-type="extra") Nothing here yet.
					else
						.anime-genres.mountable(data-mountable-type="extra")
							each genre in topGenres
								a.anime-genre.mountable(href="/genre/" + strings.ToLower(genre), data-mountable-type="genre")= genre
				
				//- Friends
				.profile-section.profile-section-friends
					h3.profile-column-header.mountable(data-mountable-type="extra") Friends

					if len(friends) == 0
						p.no-data.mountable(data-mountable-type="extra") Nothing here yet.
					else
						.profile-friends.mountable(data-mountable-type="extra")
							each friend in friends
								.profile-friend.mountable(data-mountable-type="friend")
									Avatar(friend)
				
				//- Activity
				.profile-section.profile-section-activity
					h3.profile-column-header.mountable(data-mountable-type="extra") Activity

					.profile-activities.mountable(data-mountable-type="extra")
						for month := 5; month >= 0; month--
							.activities-month
								for week := 3; week >= 0; week--
									.activities-week
										for day := 6; day >= 0; day--
											if dayToActivityCount[month * 28 + week * 7 + day] == 0
												.box.mountable(data-count="0", data-mountable-type=fmt.Sprintf("month-%d", month))
											else
												.box.tip.mountable(aria-label=fmt.Sprintf("%s: %s", time.Weekday((6 - day + 1) % 7).String(), stringutils.Plural(dayToActivityCount[month * 28 + week * 7 + day], "activity")), data-count=dayToActivityCount[month * 28 + week * 7 + day], data-mountable-type=fmt.Sprintf("month-%d", month))

											if day == 2
												.spacer-box
				
component ProfileHeader(viewUser *arn.User, user *arn.User, uri string)
	ProfileHead(viewUser, user, uri)

component ProfileHead(viewUser *arn.User, user *arn.User, uri string)
	.profile-head
		img.profile-cover.lazy(data-src=viewUser.CoverLink("large"), data-webp="true", alt="Cover image")

		.profile-image-container.mountable.never-unmount
			ProfileImage(viewUser)

		.profile-info.mountable.never-unmount
			h1#nick= viewUser.Nick
			.profile-introduction!= markdown.Render(viewUser.Introduction)
			
			.profile-tags-container
				.profile-tags
					a.profile-tag.mountable.never-unmount(href="/+" + viewUser.Nick + "/animelist/watching", data-mountable-type="header")
						Icon("list")
						span= fmt.Sprintf("%d anime", len(viewUser.AnimeList().Items))
					
					if user != nil && viewUser.Settings().Privacy.ShowAge && viewUser.Settings().Privacy.ShowGender && viewUser.AgeInYears() != 0
						.profile-tag.mountable.never-unmount(data-mountable-type="header")
							if viewUser.Gender == "male"
								Icon("mars")
							else if viewUser.Gender == "female"
								Icon("venus")
							else
								Icon("venus-mars")
							
							span= viewUser.AgeInYears()
					
					if user != nil && viewUser.Settings().Privacy.ShowLocation && viewUser.Location.CountryName != ""
						a.profile-tag.mountable.never-unmount(href="/users/country/" + strings.ToLower(viewUser.Location.CountryName), data-mountable-type="header")
							Icon("map-marker")
							span= viewUser.Location.CountryName

					if viewUser.IsPro()
						a.profile-tag.mountable.never-unmount(href="/support", aria-label="Supporter", data-mountable-type="header")
							Icon("star")
							span.profile-pro-status-text PRO
					
					if viewUser.Role != ""
						a.profile-tag.mountable.never-unmount(href="/users/staff", aria-label="Staff member", data-mountable-type="header")
							Icon("rocket")
							span= stringutils.Capitalize(viewUser.Role)
					
					if viewUser.Registered != ""
						.profile-tag.mountable.never-unmount(title="Member since", data-mountable-type="header")
							Icon("calendar")
							span= viewUser.RegisteredTime().Format("Jan 2006")

					if !viewUser.IsActive()
						.profile-tag.mountable.never-unmount(title="Hasn't been online for the past 2 weeks", data-mountable-type="header")
							Icon("bed")
							span Inactive
					
					.profile-tag.action.tip.mountable.never-unmount(data-action="showMore", data-trigger="click", aria-label="Show more", data-mountable-type="header")
						RawIcon("ellipsis-h")

					if viewUser.Website != ""
						a.profile-tag.tip.mountable.never-unmount.show-more(href=viewUser.WebsiteURL(), target="_blank", rel="noopener", aria-label=viewUser.WebsiteShortURL(), data-mountable-type="header")
							RawIcon("globe")

					if viewUser.Accounts.Osu.Nick != "" && viewUser.Accounts.Osu.PP >= 100
						a.profile-tag.tip.mountable.never-unmount.show-more(href="https://osu.ppy.sh/u/" + viewUser.Accounts.Osu.Nick, aria-label=fmt.Sprintf("osu! | %.0f pp | Level %.0f | Accuracy: %.1f%%", viewUser.Accounts.Osu.PP, viewUser.Accounts.Osu.Level, viewUser.Accounts.Osu.Accuracy), target="_blank", rel="noopener", data-mountable-type="header")
							RawIcon("trophy")

					if viewUser.Accounts.Overwatch.BattleTag != "" && viewUser.Accounts.Overwatch.SkillRating >= 1000
						a.profile-tag.tip.mountable.never-unmount.show-more(href="https://playoverwatch.com/en-us/career/pc/" + strings.Replace(viewUser.Accounts.Overwatch.BattleTag, "#", "-", 1), aria-label=fmt.Sprintf("Overwatch | %d SR | %s", viewUser.Accounts.Overwatch.SkillRating, stringutils.Capitalize(viewUser.Accounts.Overwatch.Tier)), target="_blank", rel="noopener", data-mountable-type="header")
							RawIcon("overwatch")
					
					if viewUser.Accounts.FinalFantasyXIV.Nick != "" && viewUser.Accounts.FinalFantasyXIV.Class != ""
						.profile-tag.tip.mountable.never-unmount.show-more(aria-label=fmt.Sprintf("Final Fantasy XIV | %s | Level %d | IL %d", viewUser.Accounts.FinalFantasyXIV.Class, viewUser.Accounts.FinalFantasyXIV.Level, viewUser.Accounts.FinalFantasyXIV.ItemLevel), data-mountable-type="header")
							RawIcon("gamepad")
					
					if viewUser.Accounts.Discord.Nick != "" && viewUser.Accounts.Discord.Verified
						a.profile-tag.tip.mountable.never-unmount.show-more(href="https://discord.gg/0kimAmMCeXGXuzNF", aria-label=fmt.Sprintf("Discord | %s", viewUser.Accounts.Discord.Nick), data-mountable-type="header")
							RawIcon("discord")

					if user != nil && user.ID != viewUser.ID
						a.profile-tag.tip.mountable.never-unmount.show-more(href="/compare/animelist/" + user.Nick + "/" + viewUser.Nick, aria-label="Compare", data-mountable-type="header")
							RawIcon("exchange")
					
					a.profile-tag.tip.mountable.never-unmount.show-more(href="/+" + viewUser.Nick + "/recommended/anime", aria-label="Recommendations", data-mountable-type="header")
						RawIcon("archive")

					if user != nil && (user.Role == "editor" || user.Role == "admin")
						a.profile-tag.tip.mountable.never-unmount.show-more(href="/+" + viewUser.Nick + "/log", aria-label="Log", data-mountable-type="header")
							RawIcon("list")
		
		.profile-actions
			if user != nil && user.ID != viewUser.ID
				if !user.Follows().Contains(viewUser.ID)
					button.profile-action.action.mountable.never-unmount(data-action="followUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/add/" + viewUser.ID)
						Icon("user-plus")
						span Follow
				else
					button.profile-action.action.mountable.never-unmount(data-action="unfollowUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/remove/" + viewUser.ID)
						Icon("user-times")
						span Unfollow